[libvirt] [PATCHv2 00/13] fix <domainsnapshot> indentation

A rather revamped series, based on comments from v1: https://www.redhat.com/archives/libvir-list/2011-September/msg00916.html Implementing auto-indent as part of virBuffer indeed makes things easier - I no longer have to pass around an explicit indent parameter, since it is instead part of the virBufferPtr already being passed. If you are trying to compare to the v1 thread, the correlation is: 1 - new to this series 2 - split out from 1/14 3 - new to this series 4 - new to this series 5 - compare to 2/14 6 - compare to 14/14 7 - compare to 4/14 8 - compare to 5/14 9 - compare to 9/14 10 - compare to 11/14 11 - compare to 10/14 12 - folds in changes from 3, 6, 7, 8, 12, 13/14 13 - compare to 1/14, although I'm okay with ditching this one now With just patches 1-12, there is a net reduction in lines of code in src/ (the overall series adds lines, but that's thanks to tests/). Eric Blake (13): virbuf: fix const-correctness virbuf: improve testsuite reporting virbuf: more detailed error reporting virbuf: add auto-indentation support snapshot: indent domain xml when nesting snapshot: test domainsnapshot indentation snapshot: simplify indentation of sysinfo snapshot: simplify indentation of cpu features snapshot: simplify indentation of network xml snapshot: simplify indentation of nwfilter snapshot: simplify indentation of disk encryption xml snapshot: minor cleanups from reviewing indentation virbuf: add explicit indentation functions .gitignore | 1 + src/conf/capabilities.c | 8 +- src/conf/cpu_conf.c | 42 +-- src/conf/cpu_conf.h | 9 +- src/conf/domain_conf.c | 268 +++++++------- src/conf/domain_conf.h | 5 +- src/conf/network_conf.c | 14 +- src/conf/nwfilter_conf.c | 18 +- src/conf/nwfilter_params.c | 45 +-- src/conf/nwfilter_params.h | 7 +- src/conf/storage_conf.c | 9 +- src/conf/storage_encryption_conf.c | 20 +- src/conf/storage_encryption_conf.h | 5 +- src/cpu/cpu.c | 2 +- src/libvirt_private.syms | 6 + src/qemu/qemu_driver.c | 9 +- src/qemu/qemu_migration.c | 25 +- src/util/buf.c | 258 +++++++++---- src/util/buf.h | 46 ++- src/util/network.c | 49 +-- src/util/network.h | 11 +- src/util/sysinfo.c | 399 +++++++-------------- src/util/sysinfo.h | 3 +- tests/Makefile.am | 14 +- tests/cputest.c | 2 +- tests/domainsnapshotxml2xmlout/all_parameters.xml | 2 +- tests/domainsnapshotxml2xmlout/disk_snapshot.xml | 102 +++--- tests/domainsnapshotxml2xmlout/full_domain.xml | 52 ++-- tests/domainsnapshotxml2xmltest.c | 128 +++++++ tests/testutils.c | 2 +- tests/virbuftest.c | 123 ++++++- 31 files changed, 949 insertions(+), 735 deletions(-) create mode 100644 tests/domainsnapshotxml2xmltest.c -- 1.7.4.4

Although the compiler wasn't complaining (since it was the pointer, rather than what was being pointed to, that was actually const), it looks quite suspicious to call a function with an argument labeled const when the nature of the pointer (virBufferPtr) is hidden behind a typedef. Dropping const makes the function declarations easier to read. * src/util/buf.h: Drop const from all functions that modify buffer argument. * src/util/buf.c (virBufferSetError, virBufferAdd) (virBufferContentAndReset, virBufferFreeAndReset) (virBufferAsprintf, virBufferVasprintf, virBufferEscapeString) (virBufferEscapeSexpr): Fix fallout. --- src/util/buf.c | 28 ++++++++++++++-------------- src/util/buf.h | 22 ++++++++++++---------- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/src/util/buf.c b/src/util/buf.c index 5002486..c737696 100644 --- a/src/util/buf.c +++ b/src/util/buf.c @@ -39,7 +39,7 @@ struct _virBuffer { * freeing the content and setting the error flag. */ static void -virBufferSetError(const virBufferPtr buf) +virBufferSetError(virBufferPtr buf) { VIR_FREE(buf->content); buf->size = 0; @@ -113,7 +113,7 @@ virBufferAdd(const virBufferPtr buf, const char *str, int len) /** * virBufferAddChar: - * @buf: the buffer to add to + * @buf: the buffer to append to * @c: the character to add * * Add a single character 'c' to a buffer. @@ -150,7 +150,7 @@ virBufferAddChar (virBufferPtr buf, char c) * Returns the buffer content or NULL in case of error. */ char * -virBufferContentAndReset(const virBufferPtr buf) +virBufferContentAndReset(virBufferPtr buf) { char *str; if (buf == NULL) @@ -172,7 +172,7 @@ virBufferContentAndReset(const virBufferPtr buf) * * Frees the buffer content and resets the buffer structure. */ -void virBufferFreeAndReset(const virBufferPtr buf) +void virBufferFreeAndReset(virBufferPtr buf) { char *str = virBufferContentAndReset(buf); @@ -214,14 +214,14 @@ virBufferUse(const virBufferPtr buf) /** * virBufferAsprintf: - * @buf: the buffer to dump + * @buf: the buffer to append to * @format: the format * @...: the variable list of arguments * * Do a formatted print to an XML buffer. */ void -virBufferAsprintf(const virBufferPtr buf, const char *format, ...) +virBufferAsprintf(virBufferPtr buf, const char *format, ...) { va_list argptr; va_start(argptr, format); @@ -238,7 +238,7 @@ virBufferAsprintf(const virBufferPtr buf, const char *format, ...) * Do a formatted print to an XML buffer. */ void -virBufferVasprintf(const virBufferPtr buf, const char *format, va_list argptr) +virBufferVasprintf(virBufferPtr buf, const char *format, va_list argptr) { int size, count, grow_size; va_list copy; @@ -285,7 +285,7 @@ virBufferVasprintf(const virBufferPtr buf, const char *format, va_list argptr) /** * virBufferEscapeString: - * @buf: the buffer to dump + * @buf: the buffer to append to * @format: a printf like format string but with only one %s parameter * @str: the string argument which need to be escaped * @@ -293,7 +293,7 @@ virBufferVasprintf(const virBufferPtr buf, const char *format, va_list argptr) * is escaped to avoid generating a not well-formed XML instance. */ void -virBufferEscapeString(const virBufferPtr buf, const char *format, const char *str) +virBufferEscapeString(virBufferPtr buf, const char *format, const char *str) { int len; char *escaped, *out; @@ -370,7 +370,7 @@ virBufferEscapeString(const virBufferPtr buf, const char *format, const char *st /** * virBufferEscapeSexpr: - * @buf: the buffer to dump + * @buf: the buffer to append to * @format: a printf like format string but with only one %s parameter * @str: the string argument which need to be escaped * @@ -379,7 +379,7 @@ virBufferEscapeString(const virBufferPtr buf, const char *format, const char *st * doesn't fully escape the sexpr, just enough for our code to work. */ void -virBufferEscapeSexpr(const virBufferPtr buf, +virBufferEscapeSexpr(virBufferPtr buf, const char *format, const char *str) { @@ -426,7 +426,7 @@ virBufferEscapeSexpr(const virBufferPtr buf, /** * virBufferURIEncodeString: - * @buf: the buffer to append to + * @buf: the buffer to append to * @str: the string argument which will be URI-encoded * * Append the string to the buffer. The string will be URI-encoded @@ -434,7 +434,7 @@ virBufferEscapeSexpr(const virBufferPtr buf, * with '%xx' hex sequences). */ void -virBufferURIEncodeString (virBufferPtr buf, const char *str) +virBufferURIEncodeString(virBufferPtr buf, const char *str) { int grow_size = 0; const char *p; @@ -473,7 +473,7 @@ virBufferURIEncodeString (virBufferPtr buf, const char *str) /** * virBufferStrcat: - * @buf: the buffer to dump + * @buf: the buffer to append to * @...: the variable list of strings, the last argument must be NULL * * Concatenate strings to an XML buffer. diff --git a/src/util/buf.h b/src/util/buf.h index 06d01ba..42a5044 100644 --- a/src/util/buf.h +++ b/src/util/buf.h @@ -36,21 +36,23 @@ struct _virBuffer { }; # endif -char *virBufferContentAndReset(const virBufferPtr buf); -void virBufferFreeAndReset(const virBufferPtr buf); +char *virBufferContentAndReset(virBufferPtr buf); +void virBufferFreeAndReset(virBufferPtr buf); int virBufferError(const virBufferPtr buf); unsigned int virBufferUse(const virBufferPtr buf); -void virBufferAdd(const virBufferPtr buf, const char *str, int len); -void virBufferAddChar(const virBufferPtr buf, char c); -void virBufferAsprintf(const virBufferPtr buf, const char *format, ...) +void virBufferAdd(virBufferPtr buf, const char *str, int len); +void virBufferAddChar(virBufferPtr buf, char c); +void virBufferAsprintf(virBufferPtr buf, const char *format, ...) ATTRIBUTE_FMT_PRINTF(2, 3); -void virBufferVasprintf(const virBufferPtr buf, const char *format, va_list ap) +void virBufferVasprintf(virBufferPtr buf, const char *format, va_list ap) ATTRIBUTE_FMT_PRINTF(2, 0); -void virBufferStrcat(const virBufferPtr buf, ...) +void virBufferStrcat(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(virBufferPtr buf, const char *format, + const char *str); +void virBufferEscapeSexpr(virBufferPtr buf, const char *format, + const char *str); +void virBufferURIEncodeString(virBufferPtr buf, const char *str); # define virBufferAddLit(buf_, literal_string_) \ virBufferAdd (buf_, "" literal_string_ "", sizeof literal_string_ - 1) -- 1.7.4.4

On 09/30/2011 12:22 AM, Eric Blake wrote:
Although the compiler wasn't complaining (since it was the pointer, rather than what was being pointed to, that was actually const), it looks quite suspicious to call a function with an argument labeled const when the nature of the pointer (virBufferPtr) is hidden behind a typedef. Dropping const makes the function declarations easier to read.
* src/util/buf.h: Drop const from all functions that modify buffer argument. * src/util/buf.c (virBufferSetError, virBufferAdd) (virBufferContentAndReset, virBufferFreeAndReset) (virBufferAsprintf, virBufferVasprintf, virBufferEscapeString) (virBufferEscapeSexpr): Fix fallout. --- src/util/buf.c | 28 ++++++++++++++-------------- src/util/buf.h | 22 ++++++++++++---------- 2 files changed, 26 insertions(+), 24 deletions(-)
diff --git a/src/util/buf.c b/src/util/buf.c index 5002486..c737696 100644 --- a/src/util/buf.c +++ b/src/util/buf.c @@ -39,7 +39,7 @@ struct _virBuffer { * freeing the content and setting the error flag. */ static void -virBufferSetError(const virBufferPtr buf) +virBufferSetError(virBufferPtr buf) { VIR_FREE(buf->content); buf->size = 0; @@ -113,7 +113,7 @@ virBufferAdd(const virBufferPtr buf, const char *str, int len)
Maybe a typo here?The virBufferPtr still remains const, but the declaration of this function in the buf.h shows this const is removed, too.
/** * virBufferAddChar: - * @buf: the buffer to add to + * @buf: the buffer to append to * @c: the character to add * * Add a single character 'c' to a buffer. @@ -150,7 +150,7 @@ virBufferAddChar (virBufferPtr buf, char c) * Returns the buffer content or NULL in case of error. */ char * -virBufferContentAndReset(const virBufferPtr buf) +virBufferContentAndReset(virBufferPtr buf) { char *str; if (buf == NULL) @@ -172,7 +172,7 @@ virBufferContentAndReset(const virBufferPtr buf) * * Frees the buffer content and resets the buffer structure. */ -void virBufferFreeAndReset(const virBufferPtr buf) +void virBufferFreeAndReset(virBufferPtr buf) { char *str = virBufferContentAndReset(buf);
@@ -214,14 +214,14 @@ virBufferUse(const virBufferPtr buf)
/** * virBufferAsprintf: - * @buf: the buffer to dump + * @buf: the buffer to append to * @format: the format * @...: the variable list of arguments * * Do a formatted print to an XML buffer. */ void -virBufferAsprintf(const virBufferPtr buf, const char *format, ...) +virBufferAsprintf(virBufferPtr buf, const char *format, ...) { va_list argptr; va_start(argptr, format); @@ -238,7 +238,7 @@ virBufferAsprintf(const virBufferPtr buf, const char *format, ...) * Do a formatted print to an XML buffer. */ void -virBufferVasprintf(const virBufferPtr buf, const char *format, va_list argptr) +virBufferVasprintf(virBufferPtr buf, const char *format, va_list argptr) { int size, count, grow_size; va_list copy; @@ -285,7 +285,7 @@ virBufferVasprintf(const virBufferPtr buf, const char *format, va_list argptr)
/** * virBufferEscapeString: - * @buf: the buffer to dump + * @buf: the buffer to append to * @format: a printf like format string but with only one %s parameter * @str: the string argument which need to be escaped * @@ -293,7 +293,7 @@ virBufferVasprintf(const virBufferPtr buf, const char *format, va_list argptr) * is escaped to avoid generating a not well-formed XML instance. */ void -virBufferEscapeString(const virBufferPtr buf, const char *format, const char *str) +virBufferEscapeString(virBufferPtr buf, const char *format, const char *str) { int len; char *escaped, *out; @@ -370,7 +370,7 @@ virBufferEscapeString(const virBufferPtr buf, const char *format, const char *st
/** * virBufferEscapeSexpr: - * @buf: the buffer to dump + * @buf: the buffer to append to * @format: a printf like format string but with only one %s parameter * @str: the string argument which need to be escaped * @@ -379,7 +379,7 @@ virBufferEscapeString(const virBufferPtr buf, const char *format, const char *st * doesn't fully escape the sexpr, just enough for our code to work. */ void -virBufferEscapeSexpr(const virBufferPtr buf, +virBufferEscapeSexpr(virBufferPtr buf, const char *format, const char *str) { @@ -426,7 +426,7 @@ virBufferEscapeSexpr(const virBufferPtr buf,
/** * virBufferURIEncodeString: - * @buf: the buffer to append to + * @buf: the buffer to append to * @str: the string argument which will be URI-encoded * * Append the string to the buffer. The string will be URI-encoded @@ -434,7 +434,7 @@ virBufferEscapeSexpr(const virBufferPtr buf, * with '%xx' hex sequences). */ void -virBufferURIEncodeString (virBufferPtr buf, const char *str) +virBufferURIEncodeString(virBufferPtr buf, const char *str) { int grow_size = 0; const char *p; @@ -473,7 +473,7 @@ virBufferURIEncodeString (virBufferPtr buf, const char *str)
/** * virBufferStrcat: - * @buf: the buffer to dump + * @buf: the buffer to append to * @...: the variable list of strings, the last argument must be NULL * * Concatenate strings to an XML buffer. diff --git a/src/util/buf.h b/src/util/buf.h index 06d01ba..42a5044 100644 --- a/src/util/buf.h +++ b/src/util/buf.h @@ -36,21 +36,23 @@ struct _virBuffer { }; # endif
-char *virBufferContentAndReset(const virBufferPtr buf); -void virBufferFreeAndReset(const virBufferPtr buf); +char *virBufferContentAndReset(virBufferPtr buf); +void virBufferFreeAndReset(virBufferPtr buf); int virBufferError(const virBufferPtr buf); unsigned int virBufferUse(const virBufferPtr buf); -void virBufferAdd(const virBufferPtr buf, const char *str, int len); -void virBufferAddChar(const virBufferPtr buf, char c); -void virBufferAsprintf(const virBufferPtr buf, const char *format, ...) +void virBufferAdd(virBufferPtr buf, const char *str, int len); +void virBufferAddChar(virBufferPtr buf, char c); +void virBufferAsprintf(virBufferPtr buf, const char *format, ...) ATTRIBUTE_FMT_PRINTF(2, 3); -void virBufferVasprintf(const virBufferPtr buf, const char *format, va_list ap) +void virBufferVasprintf(virBufferPtr buf, const char *format, va_list ap) ATTRIBUTE_FMT_PRINTF(2, 0); -void virBufferStrcat(const virBufferPtr buf, ...) +void virBufferStrcat(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(virBufferPtr buf, const char *format, + const char *str); +void virBufferEscapeSexpr(virBufferPtr buf, const char *format, + const char *str); +void virBufferURIEncodeString(virBufferPtr buf, const char *str);
# define virBufferAddLit(buf_, literal_string_) \ virBufferAdd (buf_, "" literal_string_ "", sizeof literal_string_ - 1)

On 10/17/2011 05:20 AM, Hai Dong Li wrote:
On 09/30/2011 12:22 AM, Eric Blake wrote:
Although the compiler wasn't complaining (since it was the pointer, rather than what was being pointed to, that was actually const), it looks quite suspicious to call a function with an argument labeled const when the nature of the pointer (virBufferPtr) is hidden behind a typedef. Dropping const makes the function declarations easier to read.
+++ b/src/util/buf.c @@ -39,7 +39,7 @@ struct _virBuffer { * freeing the content and setting the error flag. */ static void -virBufferSetError(const virBufferPtr buf) +virBufferSetError(virBufferPtr buf) { VIR_FREE(buf->content); buf->size = 0; @@ -113,7 +113,7 @@ virBufferAdd(const virBufferPtr buf, const char *str, int len)
Maybe a typo here?The virBufferPtr still remains const, but the declaration of this function in the buf.h shows this const is removed, too.
No. Rather, this is an artifact of git diff. When showing the context line for a hunk, it uses the context from the pre-patch file (where the 'const' was still present), even though the hunk itself applies to the post-patch version without 'const'. Basically, I never worry about the @@ lines - they are there as hints for where to apply the patch, and not a definitive part of the patch itself. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On 10/17/2011 10:36 PM, Eric Blake wrote:
On 10/17/2011 05:20 AM, Hai Dong Li wrote:
On 09/30/2011 12:22 AM, Eric Blake wrote:
Although the compiler wasn't complaining (since it was the pointer, rather than what was being pointed to, that was actually const), it looks quite suspicious to call a function with an argument labeled const when the nature of the pointer (virBufferPtr) is hidden behind a typedef. Dropping const makes the function declarations easier to read.
+++ b/src/util/buf.c @@ -39,7 +39,7 @@ struct _virBuffer { * freeing the content and setting the error flag. */ static void -virBufferSetError(const virBufferPtr buf) +virBufferSetError(virBufferPtr buf) { VIR_FREE(buf->content); buf->size = 0; @@ -113,7 +113,7 @@ virBufferAdd(const virBufferPtr buf, const char *str, int len)
Maybe a typo here?The virBufferPtr still remains const, but the declaration of this function in the buf.h shows this const is removed, too.
No. Rather, this is an artifact of git diff. When showing the context line for a hunk, it uses the context from the pre-patch file (where the 'const' was still present), even though the hunk itself applies to the post-patch version without 'const'. Basically, I never worry about the @@ lines - they are there as hints for where to apply the patch, and not a definitive part of the patch itself.
Okay, forget the context line. What I wanted to say is that the function virBufferAdd in the buf.c still has the const before the virBufferPtr while the declaration of this function in buf.h has const removed, after applying this patch.

On 10/17/2011 07:43 PM, Hai Dong Li wrote:
Okay, forget the context line. What I wanted to say is that the function virBufferAdd in the buf.c still has the const before the virBufferPtr while the declaration of this function in buf.h has const removed, after applying this patch.
Ah, yes, and I fixed that before pushing. On 10/19/2011 04:01 AM, Peter Krempa wrote:
On 09/29/2011 06:22 PM, Eric Blake wrote:
Although the compiler wasn't complaining (since it was the pointer, rather than what was being pointed to, that was actually const), it looks quite suspicious to call a function with an argument labeled const when the nature of the pointer (virBufferPtr) is hidden behind a typedef. Dropping const makes the function declarations easier to read.
* src/util/buf.h: Drop const from all functions that modify buffer argument. * src/util/buf.c (virBufferSetError, virBufferAdd) (virBufferContentAndReset, virBufferFreeAndReset) (virBufferAsprintf, virBufferVasprintf, virBufferEscapeString) (virBufferEscapeSexpr): Fix fallout. ---
ACK, but be careful while rebasing to current head. Some new functions were added recently to buf.[ch] and you'll get a nasty conflict on buf.h. (Dont forget to merge virBufferEscape)
Yep, I've actually had that conflict resolved locally for a couple days. Pushed now. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On 09/29/2011 06:22 PM, Eric Blake wrote:
Although the compiler wasn't complaining (since it was the pointer, rather than what was being pointed to, that was actually const), it looks quite suspicious to call a function with an argument labeled const when the nature of the pointer (virBufferPtr) is hidden behind a typedef. Dropping const makes the function declarations easier to read.
* src/util/buf.h: Drop const from all functions that modify buffer argument. * src/util/buf.c (virBufferSetError, virBufferAdd) (virBufferContentAndReset, virBufferFreeAndReset) (virBufferAsprintf, virBufferVasprintf, virBufferEscapeString) (virBufferEscapeSexpr): Fix fallout. ---
ACK, but be careful while rebasing to current head. Some new functions were added recently to buf.[ch] and you'll get a nasty conflict on buf.h. (Dont forget to merge virBufferEscape) Peter

I had some temporary test failures while working on virbuf improvements 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. * tests/testutils.c (virtTestDifference): Make it easier to diagnose test failures. --- tests/testutils.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/tests/testutils.c b/tests/testutils.c index 08db732..7eb40f0 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; -- 1.7.4.4

On 09/30/2011 12:22 AM, Eric Blake wrote:
I had some temporary test failures while working on virbuf improvements 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.
* tests/testutils.c (virtTestDifference): Make it easier to diagnose test failures. I'd like to say I like this tip. --- tests/testutils.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/tests/testutils.c b/tests/testutils.c index 08db732..7eb40f0 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;

On 10/19/2011 04:06 AM, Peter Krempa wrote:
On 09/29/2011 06:22 PM, Eric Blake wrote:
* tests/testutils.c (virtTestDifference): Make it easier to diagnose test failures. ACK,
Pushed now. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

The next patch wants to add some sanity checking, which would be a different error than ENOMEM. Many existing callers blindly report OOM failure if virBuf reports an error, and this will be wrong in the (unlikely) case that they actually had a usage error instead; but since the most common error really is ENOMEM, I'm not going to fix all callers. Meanwhile, new discriminating callers can react differently depending on what failure happened. * src/util/buf.c (virBufferSetError): Add parameter. (virBufferGrow, virBufferVasprintf, virBufferEscapeString) (virBufferEscapeSexpr): Adjust callers. --- src/util/buf.c | 26 +++++++++++++------------- 1 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/util/buf.c b/src/util/buf.c index c737696..98bb681 100644 --- a/src/util/buf.c +++ b/src/util/buf.c @@ -27,24 +27,24 @@ struct _virBuffer { unsigned int size; unsigned int use; - unsigned int error; + unsigned int error; /* errno value, or -1 for usage error */ char *content; }; /** * virBufferFail * @buf: the buffer + * @error: which error occurred (errno value, or -1 for usage) * - * Mark the buffer has having failed a memory allocation, - * freeing the content and setting the error flag. + * Mark the buffer as failed, free the content and set the error flag. */ static void -virBufferSetError(virBufferPtr buf) +virBufferSetError(virBufferPtr buf, int error) { VIR_FREE(buf->content); buf->size = 0; buf->use = 0; - buf->error = 1; + buf->error = error; } /** @@ -70,7 +70,7 @@ virBufferGrow(virBufferPtr buf, unsigned int len) size = buf->use + len + 1000; if (VIR_REALLOC_N(buf->content, size) < 0) { - virBufferSetError(buf); + virBufferSetError(buf, errno); return -1; } buf->size = size; @@ -184,15 +184,15 @@ void virBufferFreeAndReset(virBufferPtr buf) * @buf: the buffer * * Check to see if the buffer is in an error state due - * to failed memory allocation + * to failed memory allocation or usage error * - * Return true if in error, 0 if normal + * Return positive errno value or -1 on usage error, 0 if normal */ int virBufferError(const virBufferPtr buf) { if (buf == NULL) - return 1; + return -1; return buf->error; } @@ -258,7 +258,7 @@ virBufferVasprintf(virBufferPtr buf, const char *format, va_list argptr) size = buf->size - buf->use; if ((count = vsnprintf(&buf->content[buf->use], size, format, copy)) < 0) { - virBufferSetError(buf); + virBufferSetError(buf, errno); va_end(copy); return; } @@ -276,7 +276,7 @@ virBufferVasprintf(virBufferPtr buf, const char *format, va_list argptr) size = buf->size - buf->use; if ((count = vsnprintf(&buf->content[buf->use], size, format, argptr)) < 0) { - virBufferSetError(buf); + virBufferSetError(buf, errno); return; } } @@ -313,7 +313,7 @@ virBufferEscapeString(virBufferPtr buf, const char *format, const char *str) if (xalloc_oversized(6, len) || VIR_ALLOC_N(escaped, 6 * len + 1) < 0) { - virBufferSetError(buf); + virBufferSetError(buf, errno); return; } @@ -401,7 +401,7 @@ virBufferEscapeSexpr(virBufferPtr buf, if (xalloc_oversized(2, len) || VIR_ALLOC_N(escaped, 2 * len + 1) < 0) { - virBufferSetError(buf); + virBufferSetError(buf, errno); return; } -- 1.7.4.4

On 09/30/2011 12:22 AM, Eric Blake wrote:
The next patch wants to add some sanity checking, which would be a different error than ENOMEM. Many existing callers blindly report OOM failure if virBuf reports an error, and this will be wrong in the (unlikely) case that they actually had a usage error instead; but since the most common error really is ENOMEM, I'm not going to fix all callers. Meanwhile, new discriminating callers can react differently depending on what failure happened.
* src/util/buf.c (virBufferSetError): Add parameter. (virBufferGrow, virBufferVasprintf, virBufferEscapeString) (virBufferEscapeSexpr): Adjust callers. --- src/util/buf.c | 26 +++++++++++++------------- 1 files changed, 13 insertions(+), 13 deletions(-)
I checked this patch, it seems everything is all right.

On 09/29/2011 06:22 PM, Eric Blake wrote:
The next patch wants to add some sanity checking, which would be a different error than ENOMEM. Many existing callers blindly report OOM failure if virBuf reports an error, and this will be wrong in the (unlikely) case that they actually had a usage error instead; but since the most common error really is ENOMEM, I'm not going to fix all callers. Meanwhile, new discriminating callers can react differently depending on what failure happened.
* src/util/buf.c (virBufferSetError): Add parameter. (virBufferGrow, virBufferVasprintf, virBufferEscapeString) (virBufferEscapeSexpr): Adjust callers. After you rebase to current head, this patch omits to modify an call instance of virBufferSetError in the newly introduced function virBufferEscapeShell resulting into:
util/buf.c: In function 'virBufferEscapeShell': util/buf.c:563: error: too few arguments to function 'virBufferSetError' I looked trhough all instances of calling virBufferError and found none, that would check against a constant, so after this patch, everything should work as it used to. Even if it has now access to a reason of the error. ACK with that fixed Peter

On 10/19/2011 04:21 AM, Peter Krempa wrote:
On 09/29/2011 06:22 PM, Eric Blake wrote:
The next patch wants to add some sanity checking, which would be a different error than ENOMEM. Many existing callers blindly report OOM failure if virBuf reports an error, and this will be wrong in the (unlikely) case that they actually had a usage error instead; but since the most common error really is ENOMEM, I'm not going to fix all callers. Meanwhile, new discriminating callers can react differently depending on what failure happened.
* src/util/buf.c (virBufferSetError): Add parameter. (virBufferGrow, virBufferVasprintf, virBufferEscapeString) (virBufferEscapeSexpr): Adjust callers. After you rebase to current head, this patch omits to modify an call instance of virBufferSetError in the newly introduced function virBufferEscapeShell resulting into:
util/buf.c: In function 'virBufferEscapeShell': util/buf.c:563: error: too few arguments to function 'virBufferSetError'
Yep, I caught that one in my local rebase before reading your mail.
I looked trhough all instances of calling virBufferError and found none, that would check against a constant, so after this patch, everything should work as it used to. Even if it has now access to a reason of the error.
ACK with that fixed
Thanks; pushed. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

Rather than having to adjust all callers in a chain to deal with indentation, it is nicer to have virBuffer do auto-indentation. * src/util/buf.h (_virBuffer): Increase size. (virBufferAdjustIndent, virBufferGetIndent): New prototypes. * src/libvirt_private.syms (buf.h): Export new functions. * src/util/buf.c (virBufferAdjustIndent, virBufferGetIndent): New functions. (virBufferSetError, virBufferAdd, virBufferAddChar) (virBufferVasprintf, virBufferStrcat, virBufferURIEncodeString): Implement auto-indentation. * tests/virbuftest.c (testBufAutoIndent): Test it. (testBufInfiniteLoop): Don't rely on internals. Idea by Daniel P. Berrange. --- src/libvirt_private.syms | 2 + src/util/buf.c | 138 ++++++++++++++++++++++++++++----------------- src/util/buf.h | 12 +++- tests/virbuftest.c | 85 +++++++++++++++++++++++++--- 4 files changed, 172 insertions(+), 65 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index c2a3fab..695ff33 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -22,12 +22,14 @@ virBitmapString; # buf.h virBufferAdd; virBufferAddChar; +virBufferAdjustIndent; virBufferAsprintf; virBufferContentAndReset; virBufferError; virBufferEscapeSexpr; virBufferEscapeString; virBufferFreeAndReset; +virBufferGetIndent; virBufferStrcat; virBufferURIEncodeString; virBufferUse; diff --git a/src/util/buf.c b/src/util/buf.c index 98bb681..b409de4 100644 --- a/src/util/buf.c +++ b/src/util/buf.c @@ -28,6 +28,7 @@ struct _virBuffer { unsigned int size; unsigned int use; unsigned int error; /* errno value, or -1 for usage error */ + int indent; char *content; }; @@ -44,10 +45,54 @@ virBufferSetError(virBufferPtr buf, int error) VIR_FREE(buf->content); buf->size = 0; buf->use = 0; + buf->indent = 0; buf->error = error; } /** + * virBufferAdjustIndent: + * @buf: the buffer + * @indent: adjustment to make + * + * Alter the auto-indent value by adding indent (positive to increase, + * negative to decrease). Automatic indentation is performed by all + * additive functions when the existing buffer is empty or ends with a + * newline (however, note that no indentation is added if you append a + * string with an embedded newline). If @indent would cause overflow, + * the buffer error indicator is set. + */ +void +virBufferAdjustIndent(virBufferPtr buf, int indent) +{ + if (!buf || buf->error) + return; + if (indent > 0 ? INT_MAX - indent < buf->indent + : buf->indent < -indent) { + virBufferSetError(buf, -1); + return; + } + buf->indent += indent; +} + +/** + * virBufferGetIndent: + * @buf: the buffer + * @dynamic: if false, return set value; if true, return 0 unless next + * append would be affected by auto-indent + * + * Return the current auto-indent value, or -1 if there has been an error. + */ +int +virBufferGetIndent(const virBufferPtr buf, bool dynamic) +{ + if (!buf || buf->error) + return -1; + if (dynamic && buf->use && buf->content[buf->use - 1] != '\n') + return 0; + return buf->indent; +} + +/** * virBufferGrow: * @buf: the buffer * @len: the minimum free size to allocate on top of existing used space @@ -79,35 +124,39 @@ virBufferGrow(virBufferPtr buf, unsigned int len) /** * virBufferAdd: - * @buf: the buffer to add to - * @str: the string - * @len: the number of bytes to add + * @buf: the buffer to append to + * @str: the string + * @len: the number of bytes to add, or -1 * - * Add a string range to an XML buffer. if len == -1, the length of - * str is recomputed to the full string. + * Add a string range to an XML buffer. If @len == -1, the length of + * str is recomputed to the full string. Auto indentation may be applied. * */ void virBufferAdd(const virBufferPtr buf, const char *str, int len) { unsigned int needSize; + int indent; - if ((str == NULL) || (buf == NULL) || (len == 0)) + if (!str || !buf || (len == 0 && buf->indent == 0)) return; if (buf->error) return; + indent = virBufferGetIndent(buf, true); + 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'; } @@ -116,27 +165,13 @@ virBufferAdd(const virBufferPtr buf, const char *str, int len) * @buf: the buffer to append to * @c: the character to add * - * Add a single character 'c' to a buffer. + * Add a single character 'c' to a buffer. Auto indentation may be applied. * */ void -virBufferAddChar (virBufferPtr buf, char c) +virBufferAddChar(virBufferPtr buf, char c) { - unsigned int needSize; - - if (buf == NULL) - return; - - if (buf->error) - return; - - needSize = buf->use + 2; - if (needSize > buf->size && - virBufferGrow (buf, needSize - buf->use) < 0) - return; - - buf->content[buf->use++] = c; - buf->content[buf->use] = '\0'; + virBufferAdd(buf, &c, 1); } /** @@ -218,7 +253,7 @@ virBufferUse(const virBufferPtr buf) * @format: the format * @...: the variable list of arguments * - * Do a formatted print to an XML buffer. + * Do a formatted print to an XML buffer. Auto indentation may be applied. */ void virBufferAsprintf(virBufferPtr buf, const char *format, ...) @@ -231,11 +266,11 @@ virBufferAsprintf(virBufferPtr buf, const char *format, ...) /** * virBufferVasprintf: - * @buf: the buffer to dump + * @buf: the buffer to append to * @format: the format * @argptr: the variable list of arguments * - * Do a formatted print to an XML buffer. + * Do a formatted print to an XML buffer. Auto indentation may be applied. */ void virBufferVasprintf(virBufferPtr buf, const char *format, va_list argptr) @@ -249,6 +284,9 @@ virBufferVasprintf(virBufferPtr buf, const char *format, va_list argptr) if (buf->error) return; + if (buf->indent) + virBufferAdd(buf, "", -1); + if (buf->size == 0 && virBufferGrow(buf, 100) < 0) return; @@ -287,10 +325,12 @@ virBufferVasprintf(virBufferPtr buf, const char *format, va_list argptr) * virBufferEscapeString: * @buf: the buffer to append to * @format: a printf like format string but with only one %s parameter - * @str: the string argument which need to be escaped + * @str: the string argument which needs 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. + * Do a formatted print with a single string to an XML buffer. The + * string is escaped for use in XML. If @str is NULL, nothing is + * added (not even the rest of @format). Auto indentation may be + * applied. */ void virBufferEscapeString(virBufferPtr buf, const char *format, const char *str) @@ -372,11 +412,12 @@ virBufferEscapeString(virBufferPtr buf, const char *format, const char *str) * virBufferEscapeSexpr: * @buf: the buffer to append to * @format: a printf like format string but with only one %s parameter - * @str: the string argument which need to be escaped + * @str: the string argument which needs to be escaped * - * Do a formatted print with a single string to an sexpr buffer. The string - * is escaped to avoid generating a sexpr that xen will choke on. This - * doesn't fully escape the sexpr, just enough for our code to work. + * Do a formatted print with a single string to an sexpr buffer. The + * string is escaped to avoid generating a sexpr that xen will choke + * on. This doesn't fully escape the sexpr, just enough for our code + * to work. Auto indentation may be applied. */ void virBufferEscapeSexpr(virBufferPtr buf, @@ -431,7 +472,7 @@ virBufferEscapeSexpr(virBufferPtr buf, * * Append the string to the buffer. The string will be URI-encoded * during the append (ie any non alpha-numeric characters are replaced - * with '%xx' hex sequences). + * with '%xx' hex sequences). Auto indentation may be applied. */ void virBufferURIEncodeString(virBufferPtr buf, const char *str) @@ -447,6 +488,9 @@ virBufferURIEncodeString(virBufferPtr buf, const char *str) if (buf->error) return; + if (buf->indent) + virBufferAdd(buf, "", -1); + for (p = str; *p; ++p) { if (c_isalnum(*p)) grow_size++; @@ -454,7 +498,7 @@ virBufferURIEncodeString(virBufferPtr buf, const char *str) grow_size += 3; /* %ab */ } - if (virBufferGrow (buf, grow_size) < 0) + if (virBufferGrow(buf, grow_size) < 0) return; for (p = str; *p; ++p) { @@ -476,7 +520,8 @@ virBufferURIEncodeString(virBufferPtr buf, const char *str) * @buf: the buffer to append to * @...: the variable list of strings, the last argument must be NULL * - * Concatenate strings to an XML buffer. + * Concatenate strings to an XML buffer. Auto indentation may be applied + * after each string argument. */ void virBufferStrcat(virBufferPtr buf, ...) @@ -488,18 +533,7 @@ virBufferStrcat(virBufferPtr buf, ...) return; va_start(ap, buf); - - while ((str = va_arg(ap, char *)) != NULL) { - unsigned int len = strlen(str); - unsigned int needSize = buf->use + len + 2; - - if (needSize > buf->size) { - if (virBufferGrow(buf, needSize - buf->use) < 0) - break; - } - memcpy(&buf->content[buf->use], str, len); - buf->use += len; - buf->content[buf->use] = 0; - } + while ((str = va_arg(ap, char *)) != NULL) + virBufferAdd(buf, str, -1); va_end(ap); } diff --git a/src/util/buf.h b/src/util/buf.h index 42a5044..08cb727 100644 --- a/src/util/buf.h +++ b/src/util/buf.h @@ -24,15 +24,16 @@ typedef struct _virBuffer virBuffer; typedef virBuffer *virBufferPtr; # ifndef __VIR_BUFFER_C__ -# define VIR_BUFFER_INITIALIZER { 0, 0, 0, NULL } +# define VIR_BUFFER_INITIALIZER { 0, 0, 0, 0, NULL } -/* This struct must be kept in syn with the real struct +/* This struct must be kept in sync with the real struct in the buf.c impl file */ struct _virBuffer { unsigned int a; unsigned int b; unsigned int c; - char *d; + int d; + char *e; }; # endif @@ -55,6 +56,9 @@ void virBufferEscapeSexpr(virBufferPtr buf, const char *format, void virBufferURIEncodeString(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 virBufferAdjustIndent(virBufferPtr buf, int indent); +int virBufferGetIndent(const virBufferPtr buf, bool dynamic); #endif /* __VIR_BUFFER_H__ */ diff --git a/tests/virbuftest.c b/tests/virbuftest.c index 01db313..2f94e1c 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; @@ -28,18 +28,13 @@ static int testBufInfiniteLoop(const void *data ATTRIBUTE_UNUSED) int ret = -1; const struct testInfo *info = data; - /* This relies of virBuffer internals, so may break if things change - * in the future */ virBufferAddChar(buf, 'a'); - if (buf->a != 1002 || buf->b != 1) { - TEST_ERROR("Buf was not expected size, size=%d use=%d\n", - buf->a, buf->b); - goto out; - } /* - * Infinite loop triggers if: + * Infinite loop used to trigger if: * (strlen + 1 > 1000) && (strlen == buf-size - buf-use - 1) + * which was the case after the above addchar at the time of the bug. + * This test is a bit fragile, since it relies on virBuffer internals. */ if (virAsprintf(&addstr, "%*s", buf->a - buf->b - 1, "a") < 0) { goto out; @@ -63,6 +58,77 @@ out: return ret; } +static int testBufAutoIndent(const void *data ATTRIBUTE_UNUSED) +{ + virBuffer bufinit = VIR_BUFFER_INITIALIZER; + virBufferPtr buf = &bufinit; + const char expected[] = + " 1\n 2\n 3\n 4\n 5\n 6\n 7\n &\n 8\n 9\n"; + char *result = NULL; + int ret = 0; + + if (virBufferGetIndent(buf, false) != 0 || + virBufferGetIndent(buf, true) != 0) { + TEST_ERROR("Wrong indentation"); + ret = -1; + } + virBufferAdjustIndent(buf, 3); + if (virBufferGetIndent(buf, false) != 3 || + virBufferGetIndent(buf, true) != 3 || + virBufferError(buf)) { + TEST_ERROR("Wrong indentation"); + ret = -1; + } + virBufferAdjustIndent(buf, -2); + if (virBufferGetIndent(buf, false) != 1 || + virBufferGetIndent(buf, true) != 1 || + virBufferError(buf)) { + TEST_ERROR("Wrong indentation"); + ret = -1; + } + virBufferAdjustIndent(buf, -2); + if (virBufferGetIndent(buf, false) != -1 || + virBufferGetIndent(buf, true) != -1 || + virBufferError(buf) != -1) { + TEST_ERROR("Usage error not flagged"); + ret = -1; + } + virBufferFreeAndReset(buf); + if (virBufferGetIndent(buf, false) != 0 || + virBufferGetIndent(buf, true) != 0 || + virBufferError(buf)) { + TEST_ERROR("Reset didn't clear indentation"); + ret = -1; + } + virBufferAdjustIndent(buf, 2); + virBufferAddLit(buf, "1"); + if (virBufferGetIndent(buf, false) != 2 || + virBufferGetIndent(buf, true) != 0) { + TEST_ERROR("Wrong indentation"); + ret = -1; + } + virBufferAddLit(buf, "\n"); + virBufferAdd(buf, "" "2\n", -1); /* Extra "" appeases syntax-check */ + virBufferAddChar(buf, '3'); + virBufferAddChar(buf, '\n'); + virBufferAsprintf(buf, "%d", 4); + virBufferAsprintf(buf, "%c", '\n'); + virBufferStrcat(buf, "5", "\n", "6\n", NULL); + virBufferEscapeString(buf, "%s\n", "7"); + virBufferEscapeString(buf, "%s\n", "&"); + virBufferEscapeSexpr(buf, "%s", "8\n"); + virBufferURIEncodeString(buf, "9"); + virBufferAddChar(buf, '\n'); + + result = virBufferContentAndReset(buf); + if (!result || STRNEQ(result, expected)) { + virtTestDifference(stderr, expected, result); + ret = -1; + } + VIR_FREE(result); + return ret; +} + static int mymain(void) { @@ -78,6 +144,7 @@ mymain(void) DO_TEST("EscapeString infinite loop", testBufInfiniteLoop, 1); DO_TEST("VSprintf infinite loop", testBufInfiniteLoop, 0); + DO_TEST("Auto-indentation", testBufAutoIndent, 0); return(ret==0 ? EXIT_SUCCESS : EXIT_FAILURE); } -- 1.7.4.4

Rather than having to adjust all callers in a chain to deal with indentation, it is nicer to have virBuffer do auto-indentation.
* src/util/buf.h (_virBuffer): Increase size. (virBufferAdjustIndent, virBufferGetIndent): New prototypes. * src/libvirt_private.syms (buf.h): Export new functions. * src/util/buf.c (virBufferAdjustIndent, virBufferGetIndent): New functions. (virBufferSetError, virBufferAdd, virBufferAddChar) (virBufferVasprintf, virBufferStrcat, virBufferURIEncodeString): Implement auto-indentation. * tests/virbuftest.c (testBufAutoIndent): Test it. (testBufInfiniteLoop): Don't rely on internals. Idea by Daniel P. Berrange. --- src/libvirt_private.syms | 2 + src/util/buf.c | 138 ++++++++++++++++++++++++++++----------------- src/util/buf.h | 12 +++- tests/virbuftest.c | 85 +++++++++++++++++++++++++--- 4 files changed, 172 insertions(+), 65 deletions(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index c2a3fab..695ff33 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -22,12 +22,14 @@ virBitmapString; # buf.h virBufferAdd; virBufferAddChar; +virBufferAdjustIndent; virBufferAsprintf; virBufferContentAndReset; virBufferError; virBufferEscapeSexpr; virBufferEscapeString; virBufferFreeAndReset; +virBufferGetIndent; virBufferStrcat; virBufferURIEncodeString; virBufferUse; diff --git a/src/util/buf.c b/src/util/buf.c index 98bb681..b409de4 100644 --- a/src/util/buf.c +++ b/src/util/buf.c @@ -28,6 +28,7 @@ struct _virBuffer { unsigned int size; unsigned int use; unsigned int error; /* errno value, or -1 for usage error */ + int indent; char *content; };
@@ -44,10 +45,54 @@ virBufferSetError(virBufferPtr buf, int error) VIR_FREE(buf->content); buf->size = 0; buf->use = 0; + buf->indent = 0; buf->error = error; }
/** + * virBufferAdjustIndent: + * @buf: the buffer + * @indent: adjustment to make + * + * Alter the auto-indent value by adding indent (positive to increase, + * negative to decrease). Automatic indentation is performed by all + * additive functions when the existing buffer is empty or ends with a + * newline (however, note that no indentation is added if you append a + * string with an embedded newline). If @indent would cause overflow, + * the buffer error indicator is set. + */ +void +virBufferAdjustIndent(virBufferPtr buf, int indent) +{ + if (!buf || buf->error) + return; + if (indent> 0 ? INT_MAX - indent< buf->indent The priority of operators is all right here, yet maybe parentheses around the expression (INT_MAX - indent) will make this more obviously?. Just saying, never mind. + : buf->indent< -indent) { + virBufferSetError(buf, -1); + return; + } + buf->indent += indent; +} + +/** + * virBufferGetIndent: + * @buf: the buffer + * @dynamic: if false, return set value; if true, return 0 unless next + * append would be affected by auto-indent + * + * Return the current auto-indent value, or -1 if there has been an error. + */ +int +virBufferGetIndent(const virBufferPtr buf, bool dynamic) +{ + if (!buf || buf->error) + return -1; + if (dynamic&& buf->use&& buf->content[buf->use - 1] != '\n') + return 0; + return buf->indent; +} + +/** * virBufferGrow: * @buf: the buffer * @len: the minimum free size to allocate on top of existing used space @@ -79,35 +124,39 @@ virBufferGrow(virBufferPtr buf, unsigned int len)
/** * virBufferAdd: - * @buf: the buffer to add to - * @str: the string - * @len: the number of bytes to add + * @buf: the buffer to append to + * @str: the string + * @len: the number of bytes to add, or -1 * - * Add a string range to an XML buffer. if len == -1, the length of - * str is recomputed to the full string. + * Add a string range to an XML buffer. If @len == -1, the length of + * str is recomputed to the full string. Auto indentation may be applied. * */ void virBufferAdd(const virBufferPtr buf, const char *str, int len) { unsigned int needSize; + int indent;
- if ((str == NULL) || (buf == NULL) || (len == 0)) + if (!str || !buf || (len == 0&& buf->indent == 0)) return;
if (buf->error) return;
+ indent = virBufferGetIndent(buf, true); + 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'; }
@@ -116,27 +165,13 @@ virBufferAdd(const virBufferPtr buf, const char *str, int len) * @buf: the buffer to append to * @c: the character to add * - * Add a single character 'c' to a buffer. + * Add a single character 'c' to a buffer. Auto indentation may be applied. * */ void -virBufferAddChar (virBufferPtr buf, char c) +virBufferAddChar(virBufferPtr buf, char c) { - unsigned int needSize; - - if (buf == NULL) - return; - - if (buf->error) - return; - - needSize = buf->use + 2; - if (needSize> buf->size&& - virBufferGrow (buf, needSize - buf->use)< 0) - return; - - buf->content[buf->use++] = c; - buf->content[buf->use] = '\0'; + virBufferAdd(buf,&c, 1); }
/** @@ -218,7 +253,7 @@ virBufferUse(const virBufferPtr buf) * @format: the format * @...: the variable list of arguments * - * Do a formatted print to an XML buffer. + * Do a formatted print to an XML buffer. Auto indentation may be applied. */ void virBufferAsprintf(virBufferPtr buf, const char *format, ...) @@ -231,11 +266,11 @@ virBufferAsprintf(virBufferPtr buf, const char *format, ...)
/** * virBufferVasprintf: - * @buf: the buffer to dump + * @buf: the buffer to append to * @format: the format * @argptr: the variable list of arguments * - * Do a formatted print to an XML buffer. + * Do a formatted print to an XML buffer. Auto indentation may be applied. */ void virBufferVasprintf(virBufferPtr buf, const char *format, va_list argptr) @@ -249,6 +284,9 @@ virBufferVasprintf(virBufferPtr buf, const char *format, va_list argptr) if (buf->error) return;
+ if (buf->indent) + virBufferAdd(buf, "", -1); + if (buf->size == 0&& virBufferGrow(buf, 100)< 0) return; @@ -287,10 +325,12 @@ virBufferVasprintf(virBufferPtr buf, const char *format, va_list argptr) * virBufferEscapeString: * @buf: the buffer to append to * @format: a printf like format string but with only one %s parameter - * @str: the string argument which need to be escaped + * @str: the string argument which needs 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. + * Do a formatted print with a single string to an XML buffer. The + * string is escaped for use in XML. If @str is NULL, nothing is + * added (not even the rest of @format). Auto indentation may be + * applied. */ void virBufferEscapeString(virBufferPtr buf, const char *format, const char *str) @@ -372,11 +412,12 @@ virBufferEscapeString(virBufferPtr buf, const char *format, const char *str) * virBufferEscapeSexpr: * @buf: the buffer to append to * @format: a printf like format string but with only one %s parameter - * @str: the string argument which need to be escaped + * @str: the string argument which needs to be escaped * - * Do a formatted print with a single string to an sexpr buffer. The string - * is escaped to avoid generating a sexpr that xen will choke on. This - * doesn't fully escape the sexpr, just enough for our code to work. + * Do a formatted print with a single string to an sexpr buffer. The + * string is escaped to avoid generating a sexpr that xen will choke + * on. This doesn't fully escape the sexpr, just enough for our code + * to work. Auto indentation may be applied. */ void virBufferEscapeSexpr(virBufferPtr buf, @@ -431,7 +472,7 @@ virBufferEscapeSexpr(virBufferPtr buf, * * Append the string to the buffer. The string will be URI-encoded * during the append (ie any non alpha-numeric characters are replaced - * with '%xx' hex sequences). + * with '%xx' hex sequences). Auto indentation may be applied. */ void virBufferURIEncodeString(virBufferPtr buf, const char *str) @@ -447,6 +488,9 @@ virBufferURIEncodeString(virBufferPtr buf, const char *str) if (buf->error) return;
+ if (buf->indent) + virBufferAdd(buf, "", -1); + for (p = str; *p; ++p) { if (c_isalnum(*p)) grow_size++; @@ -454,7 +498,7 @@ virBufferURIEncodeString(virBufferPtr buf, const char *str) grow_size += 3; /* %ab */ }
- if (virBufferGrow (buf, grow_size)< 0) + if (virBufferGrow(buf, grow_size)< 0) return;
for (p = str; *p; ++p) { @@ -476,7 +520,8 @@ virBufferURIEncodeString(virBufferPtr buf, const char *str) * @buf: the buffer to append to * @...: the variable list of strings, the last argument must be NULL * - * Concatenate strings to an XML buffer. + * Concatenate strings to an XML buffer. Auto indentation may be applied + * after each string argument. */ void virBufferStrcat(virBufferPtr buf, ...) @@ -488,18 +533,7 @@ virBufferStrcat(virBufferPtr buf, ...) return;
va_start(ap, buf); - - while ((str = va_arg(ap, char *)) != NULL) { - unsigned int len = strlen(str); - unsigned int needSize = buf->use + len + 2; - - if (needSize> buf->size) { - if (virBufferGrow(buf, needSize - buf->use)< 0) - break; - } - memcpy(&buf->content[buf->use], str, len); - buf->use += len; - buf->content[buf->use] = 0; - } + while ((str = va_arg(ap, char *)) != NULL) + virBufferAdd(buf, str, -1); va_end(ap); } diff --git a/src/util/buf.h b/src/util/buf.h index 42a5044..08cb727 100644 --- a/src/util/buf.h +++ b/src/util/buf.h @@ -24,15 +24,16 @@ typedef struct _virBuffer virBuffer; typedef virBuffer *virBufferPtr;
# ifndef __VIR_BUFFER_C__ -# define VIR_BUFFER_INITIALIZER { 0, 0, 0, NULL } +# define VIR_BUFFER_INITIALIZER { 0, 0, 0, 0, NULL }
-/* This struct must be kept in syn with the real struct +/* This struct must be kept in sync with the real struct in the buf.c impl file */ struct _virBuffer { unsigned int a; unsigned int b; unsigned int c; - char *d; + int d; + char *e; }; # endif
@@ -55,6 +56,9 @@ void virBufferEscapeSexpr(virBufferPtr buf, const char *format, void virBufferURIEncodeString(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 virBufferAdjustIndent(virBufferPtr buf, int indent); +int virBufferGetIndent(const virBufferPtr buf, bool dynamic);
#endif /* __VIR_BUFFER_H__ */ diff --git a/tests/virbuftest.c b/tests/virbuftest.c index 01db313..2f94e1c 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; @@ -28,18 +28,13 @@ static int testBufInfiniteLoop(const void *data ATTRIBUTE_UNUSED) int ret = -1; const struct testInfo *info = data;
- /* This relies of virBuffer internals, so may break if things change - * in the future */ virBufferAddChar(buf, 'a'); - if (buf->a != 1002 || buf->b != 1) { - TEST_ERROR("Buf was not expected size, size=%d use=%d\n", - buf->a, buf->b); - goto out; - }
/* - * Infinite loop triggers if: + * Infinite loop used to trigger if: * (strlen + 1> 1000)&& (strlen == buf-size - buf-use - 1) + * which was the case after the above addchar at the time of the bug. + * This test is a bit fragile, since it relies on virBuffer internals. */ if (virAsprintf(&addstr, "%*s", buf->a - buf->b - 1, "a")< 0) { goto out; @@ -63,6 +58,77 @@ out: return ret; }
+static int testBufAutoIndent(const void *data ATTRIBUTE_UNUSED) +{ + virBuffer bufinit = VIR_BUFFER_INITIALIZER; + virBufferPtr buf =&bufinit; + const char expected[] = + " 1\n 2\n 3\n 4\n 5\n 6\n 7\n&\n 8\n 9\n"; + char *result = NULL; + int ret = 0; + + if (virBufferGetIndent(buf, false) != 0 || + virBufferGetIndent(buf, true) != 0) { + TEST_ERROR("Wrong indentation"); + ret = -1; + } + virBufferAdjustIndent(buf, 3); + if (virBufferGetIndent(buf, false) != 3 || + virBufferGetIndent(buf, true) != 3 || + virBufferError(buf)) { + TEST_ERROR("Wrong indentation"); + ret = -1; + } + virBufferAdjustIndent(buf, -2); + if (virBufferGetIndent(buf, false) != 1 || + virBufferGetIndent(buf, true) != 1 || + virBufferError(buf)) { + TEST_ERROR("Wrong indentation"); + ret = -1; + } So now buf->indent is 1. Go to the next step, the indent is given -2 again, see what will happen. if virBufferAdjustIndent failed to check the indent overflow, the buf->indent will be -1,too, so it may avoid the check (virBufferGetIndent(buf, false) != -1) and (virBufferGetIndent(buf,
On 09/30/2011 12:22 AM, Eric Blake wrote: true) != -1).
+ virBufferAdjustIndent(buf, -2); So I think -3 may be better. + if (virBufferGetIndent(buf, false) != -1 || + virBufferGetIndent(buf, true) != -1 || + virBufferError(buf) != -1) { + TEST_ERROR("Usage error not flagged"); + ret = -1; + } + virBufferFreeAndReset(buf); + if (virBufferGetIndent(buf, false) != 0 || + virBufferGetIndent(buf, true) != 0 || + virBufferError(buf)) { + TEST_ERROR("Reset didn't clear indentation"); + ret = -1; + } + virBufferAdjustIndent(buf, 2); + virBufferAddLit(buf, "1"); + if (virBufferGetIndent(buf, false) != 2 || + virBufferGetIndent(buf, true) != 0) { + TEST_ERROR("Wrong indentation"); + ret = -1; + } + virBufferAddLit(buf, "\n"); + virBufferAdd(buf, "" "2\n", -1); /* Extra "" appeases syntax-check */ + virBufferAddChar(buf, '3'); + virBufferAddChar(buf, '\n'); + virBufferAsprintf(buf, "%d", 4); + virBufferAsprintf(buf, "%c", '\n'); + virBufferStrcat(buf, "5", "\n", "6\n", NULL); + virBufferEscapeString(buf, "%s\n", "7"); + virBufferEscapeString(buf, "%s\n", "&"); + virBufferEscapeSexpr(buf, "%s", "8\n"); + virBufferURIEncodeString(buf, "9"); + virBufferAddChar(buf, '\n'); + + result = virBufferContentAndReset(buf); + if (!result || STRNEQ(result, expected)) { + virtTestDifference(stderr, expected, result); + ret = -1; + } + VIR_FREE(result); + return ret; +} + static int mymain(void) { @@ -78,6 +144,7 @@ mymain(void)
DO_TEST("EscapeString infinite loop", testBufInfiniteLoop, 1); DO_TEST("VSprintf infinite loop", testBufInfiniteLoop, 0); + DO_TEST("Auto-indentation", testBufAutoIndent, 0);
return(ret==0 ? EXIT_SUCCESS : EXIT_FAILURE); }

On 09/30/2011 12:22 AM, Eric Blake wrote:
Rather than having to adjust all callers in a chain to deal with indentation, it is nicer to have virBuffer do auto-indentation.
* src/util/buf.h (_virBuffer): Increase size. (virBufferAdjustIndent, virBufferGetIndent): New prototypes. * src/libvirt_private.syms (buf.h): Export new functions. * src/util/buf.c (virBufferAdjustIndent, virBufferGetIndent): New functions. (virBufferSetError, virBufferAdd, virBufferAddChar) (virBufferVasprintf, virBufferStrcat, virBufferURIEncodeString): Implement auto-indentation. * tests/virbuftest.c (testBufAutoIndent): Test it. (testBufInfiniteLoop): Don't rely on internals. Idea by Daniel P. Berrange. --- src/libvirt_private.syms | 2 + src/util/buf.c | 138 ++++++++++++++++++++++++++++----------------- src/util/buf.h | 12 +++- tests/virbuftest.c | 85 +++++++++++++++++++++++++--- 4 files changed, 172 insertions(+), 65 deletions(-)
+static int testBufAutoIndent(const void *data ATTRIBUTE_UNUSED) +{ + virBuffer bufinit = VIR_BUFFER_INITIALIZER; + virBufferPtr buf =&bufinit; + const char expected[] = + " 1\n 2\n 3\n 4\n 5\n 6\n 7\n&\n 8\n 9\n"; + char *result = NULL; + int ret = 0; + + if (virBufferGetIndent(buf, false) != 0 || + virBufferGetIndent(buf, true) != 0) { + TEST_ERROR("Wrong indentation"); + ret = -1; + } + virBufferAdjustIndent(buf, 3); + if (virBufferGetIndent(buf, false) != 3 || + virBufferGetIndent(buf, true) != 3 || + virBufferError(buf)) { + TEST_ERROR("Wrong indentation"); + ret = -1; + } + virBufferAdjustIndent(buf, -2); + if (virBufferGetIndent(buf, false) != 1 || + virBufferGetIndent(buf, true) != 1 || + virBufferError(buf)) { + TEST_ERROR("Wrong indentation"); + ret = -1; + } + virBufferAdjustIndent(buf, -2); + if (virBufferGetIndent(buf, false) != -1 || + virBufferGetIndent(buf, true) != -1 || + virBufferError(buf) != -1) { + TEST_ERROR("Usage error not flagged"); + ret = -1; + } + virBufferFreeAndReset(buf); + if (virBufferGetIndent(buf, false) != 0 || + virBufferGetIndent(buf, true) != 0 || + virBufferError(buf)) { + TEST_ERROR("Reset didn't clear indentation"); + ret = -1; + } + virBufferAdjustIndent(buf, 2); + virBufferAddLit(buf, "1"); + if (virBufferGetIndent(buf, false) != 2 || + virBufferGetIndent(buf, true) != 0) { + TEST_ERROR("Wrong indentation"); + ret = -1; + } + virBufferAddLit(buf, "\n"); + virBufferAdd(buf, "" "2\n", -1); /* Extra "" appeases syntax-check */ + virBufferAddChar(buf, '3'); + virBufferAddChar(buf, '\n'); + virBufferAsprintf(buf, "%d", 4); + virBufferAsprintf(buf, "%c", '\n'); + virBufferStrcat(buf, "5", "\n", "6\n", NULL); + virBufferEscapeString(buf, "%s\n", "7"); + virBufferEscapeString(buf, "%s\n", "&"); + virBufferEscapeSexpr(buf, "%s", "8\n"); + virBufferURIEncodeString(buf, "9"); + virBufferAddChar(buf, '\n'); + + result = virBufferContentAndReset(buf); + if (!result || STRNEQ(result, expected)) { + virtTestDifference(stderr, expected, result); + ret = -1; + } + VIR_FREE(result); + return ret; +} Let me express my appreciation towards this testBufAutoIndent() function, by the way. It's beautiful. + static int mymain(void) { @@ -78,6 +144,7 @@ mymain(void)
DO_TEST("EscapeString infinite loop", testBufInfiniteLoop, 1); DO_TEST("VSprintf infinite loop", testBufInfiniteLoop, 0); + DO_TEST("Auto-indentation", testBufAutoIndent, 0);
return(ret==0 ? EXIT_SUCCESS : EXIT_FAILURE); }

Rather than having to adjust all callers in a chain to deal with indentation, it is nicer to have virBuffer do auto-indentation.
* src/util/buf.h (_virBuffer): Increase size. (virBufferAdjustIndent, virBufferGetIndent): New prototypes. * src/libvirt_private.syms (buf.h): Export new functions. * src/util/buf.c (virBufferAdjustIndent, virBufferGetIndent): New functions. (virBufferSetError, virBufferAdd, virBufferAddChar) (virBufferVasprintf, virBufferStrcat, virBufferURIEncodeString): Implement auto-indentation. * tests/virbuftest.c (testBufAutoIndent): Test it. (testBufInfiniteLoop): Don't rely on internals. Idea by Daniel P. Berrange. --- src/libvirt_private.syms | 2 + src/util/buf.c | 138 ++++++++++++++++++++++++++++----------------- src/util/buf.h | 12 +++- tests/virbuftest.c | 85 +++++++++++++++++++++++++--- 4 files changed, 172 insertions(+), 65 deletions(-)
@@ -79,35 +124,39 @@ virBufferGrow(virBufferPtr buf, unsigned int len)
/** * virBufferAdd: - * @buf: the buffer to add to - * @str: the string - * @len: the number of bytes to add + * @buf: the buffer to append to + * @str: the string + * @len: the number of bytes to add, or -1 * - * Add a string range to an XML buffer. if len == -1, the length of - * str is recomputed to the full string. + * Add a string range to an XML buffer. If @len == -1, the length of + * str is recomputed to the full string. Auto indentation may be applied. * */ void virBufferAdd(const virBufferPtr buf, const char *str, int len) { unsigned int needSize; + int indent; /* context for a later comment */ - if ((str == NULL) || (buf == NULL) || (len == 0)) + if (!str || !buf || (len == 0&& buf->indent == 0)) return;
if (buf->error) return;
+ indent = virBufferGetIndent(buf, true); + 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'; }
@@ -116,27 +165,13 @@ virBufferAdd(const virBufferPtr buf, const char *str, int len) * @buf: the buffer to append to * @c: the character to add * - * Add a single character 'c' to a buffer. + * Add a single character 'c' to a buffer. Auto indentation may be applied. * */ void -virBufferAddChar (virBufferPtr buf, char c) +virBufferAddChar(virBufferPtr buf, char c) { - unsigned int needSize; - - if (buf == NULL) - return; - - if (buf->error) - return; - - needSize = buf->use + 2; - if (needSize> buf->size&& - virBufferGrow (buf, needSize - buf->use)< 0) - return; - - buf->content[buf->use++] = c; - buf->content[buf->use] = '\0'; + virBufferAdd(buf,&c, 1); } This has slightly more overhead than the previous version, but I don't
/** @@ -218,7 +253,7 @@ virBufferUse(const virBufferPtr buf) * @format: the format * @...: the variable list of arguments * - * Do a formatted print to an XML buffer. + * Do a formatted print to an XML buffer. Auto indentation may be applied. */ void virBufferAsprintf(virBufferPtr buf, const char *format, ...) @@ -231,11 +266,11 @@ virBufferAsprintf(virBufferPtr buf, const char *format, ...)
/** * virBufferVasprintf: - * @buf: the buffer to dump + * @buf: the buffer to append to * @format: the format * @argptr: the variable list of arguments * - * Do a formatted print to an XML buffer. + * Do a formatted print to an XML buffer. Auto indentation may be applied. */ void virBufferVasprintf(virBufferPtr buf, const char *format, va_list argptr) @@ -249,6 +284,9 @@ virBufferVasprintf(virBufferPtr buf, const char *format, va_list argptr) if (buf->error) return;
+ if (buf->indent) + virBufferAdd(buf, "", -1); + virBufferAdd is a no-op, if this expression is true (see context above): " if (!str || !buf || (len == 0 && buf->indent == 0))". You could save a call to strlen and the if clause if you call virBufferAdd(buf, "", 0) The len=0 will be automaticaly used (as the only way to accept len==0 as a correct value is if indentation is requested). You can also save a
On 09/29/2011 06:22 PM, Eric Blake wrote: think adding a char is such a common operation that it would impact performance. This also simplifies mantenance. I like it. line with the if clause and call it directly. ( Looks like you've prepared it for this to happen :D)
if (buf->size == 0&& virBufferGrow(buf, 100)< 0) return; @@ -431,7 +472,7 @@ virBufferEscapeSexpr(virBufferPtr buf, * * Append the string to the buffer. The string will be URI-encoded * during the append (ie any non alpha-numeric characters are replaced - * with '%xx' hex sequences). + * with '%xx' hex sequences). Auto indentation may be applied. */ void virBufferURIEncodeString(virBufferPtr buf, const char *str) @@ -447,6 +488,9 @@ virBufferURIEncodeString(virBufferPtr buf, const char *str) if (buf->error) return;
+ if (buf->indent) + virBufferAdd(buf, "", -1);
Same as above ...
@@ -476,7 +520,8 @@ virBufferURIEncodeString(virBufferPtr buf, const char *str) * @buf: the buffer to append to * @...: the variable list of strings, the last argument must be NULL * - * Concatenate strings to an XML buffer. + * Concatenate strings to an XML buffer. Auto indentation may be applied + * after each string argument. */ void virBufferStrcat(virBufferPtr buf, ...) @@ -488,18 +533,7 @@ virBufferStrcat(virBufferPtr buf, ...) return;
va_start(ap, buf); - - while ((str = va_arg(ap, char *)) != NULL) { - unsigned int len = strlen(str); - unsigned int needSize = buf->use + len + 2; - - if (needSize> buf->size) { - if (virBufferGrow(buf, needSize - buf->use)< 0) - break; - } - memcpy(&buf->content[buf->use], str, len); - buf->use += len; - buf->content[buf->use] = 0; - } + while ((str = va_arg(ap, char *)) != NULL) + virBufferAdd(buf, str, -1); va_end(ap); } Elegant. diff --git a/tests/virbuftest.c b/tests/virbuftest.c
The tests look fine to me and it's nice to have them. ACK, Peter

On 10/19/2011 11:51 AM, Peter Krempa wrote:
On 09/29/2011 06:22 PM, Eric Blake wrote:
Rather than having to adjust all callers in a chain to deal with indentation, it is nicer to have virBuffer do auto-indentation.
virBufferAdd(const virBufferPtr buf, const char *str, int len) { unsigned int needSize; + int indent; /* context for a later comment */ - if ((str == NULL) || (buf == NULL) || (len == 0)) + if (!str || !buf || (len == 0&& buf->indent == 0)) return;
@@ -249,6 +284,9 @@ virBufferVasprintf(virBufferPtr buf, const char *format, va_list argptr) if (buf->error) return;
+ if (buf->indent) + virBufferAdd(buf, "", -1); + virBufferAdd is a no-op, if this expression is true (see context above): " if (!str || !buf || (len == 0 && buf->indent == 0))". You could save a call to strlen and the if clause if you call virBufferAdd(buf, "", 0) The len=0 will be automaticaly used (as the only way to accept len==0 as a correct value is if indentation is requested). You can also save a line with the if clause and call it directly. ( Looks like you've prepared it for this to happen :D)
Okay, I simplified these two lines down to one.
diff --git a/tests/virbuftest.c b/tests/virbuftest.c
The tests look fine to me and it's nice to have them.
Yet they missed out on the new stuff in the meantime.
ACK,
Here's what I squashed before pushing: diff --git i/src/util/buf.c w/src/util/buf.c index 3dd9a72..ac5360c 100644 --- i/src/util/buf.c +++ w/src/util/buf.c @@ -284,8 +284,7 @@ virBufferVasprintf(virBufferPtr buf, const char *format, va_list argptr) if (buf->error) return; - if (buf->indent) - virBufferAddLit(buf, ""); + virBufferAddLit(buf, ""); /* auto-indent */ if (buf->size == 0 && virBufferGrow(buf, 100) < 0) @@ -500,8 +499,7 @@ virBufferURIEncodeString(virBufferPtr buf, const char *str) if (buf->error) return; - if (buf->indent) - virBufferAddLit(buf, ""); + virBufferAddLit(buf, ""); /* auto-indent */ for (p = str; *p; ++p) { if (c_isalnum(*p)) diff --git i/tests/virbuftest.c w/tests/virbuftest.c index 2f94e1c..bc53959 100644 --- i/tests/virbuftest.c +++ w/tests/virbuftest.c @@ -63,7 +63,7 @@ static int testBufAutoIndent(const void *data ATTRIBUTE_UNUSED) virBuffer bufinit = VIR_BUFFER_INITIALIZER; virBufferPtr buf = &bufinit; const char expected[] = - " 1\n 2\n 3\n 4\n 5\n 6\n 7\n &\n 8\n 9\n"; + " 1\n 2\n 3\n 4\n 5\n 6\n 7\n &\n 8\n 9\n 10\n ' 11'\n"; char *result = NULL; int ret = 0; @@ -86,7 +86,7 @@ static int testBufAutoIndent(const void *data ATTRIBUTE_UNUSED) TEST_ERROR("Wrong indentation"); ret = -1; } - virBufferAdjustIndent(buf, -2); + virBufferAdjustIndent(buf, -3); if (virBufferGetIndent(buf, false) != -1 || virBufferGetIndent(buf, true) != -1 || virBufferError(buf) != -1) { @@ -119,6 +119,10 @@ static int testBufAutoIndent(const void *data ATTRIBUTE_UNUSED) virBufferEscapeSexpr(buf, "%s", "8\n"); virBufferURIEncodeString(buf, "9"); virBufferAddChar(buf, '\n'); + virBufferEscapeShell(buf, "10"); + virBufferAddChar(buf, '\n'); + virBufferEscapeShell(buf, " 11"); + virBufferAddChar(buf, '\n'); result = virBufferContentAndReset(buf); if (!result || STRNEQ(result, expected)) { -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

Rather than having to adjust all callers in a chain to deal with indentation, it is nicer to have virBuffer do auto-indentation.
* src/util/buf.h (_virBuffer): Increase size. (virBufferAdjustIndent, virBufferGetIndent): New prototypes. * src/libvirt_private.syms (buf.h): Export new functions. * src/util/buf.c (virBufferAdjustIndent, virBufferGetIndent): New functions. (virBufferSetError, virBufferAdd, virBufferAddChar) (virBufferVasprintf, virBufferStrcat, virBufferURIEncodeString): Implement auto-indentation. * tests/virbuftest.c (testBufAutoIndent): Test it. (testBufInfiniteLoop): Don't rely on internals. Idea by Daniel P. Berrange. --- src/libvirt_private.syms | 2 + src/util/buf.c | 138 ++++++++++++++++++++++++++++----------------- src/util/buf.h | 12 +++- tests/virbuftest.c | 85 +++++++++++++++++++++++++--- 4 files changed, 172 insertions(+), 65 deletions(-)
diff --git a/tests/virbuftest.c b/tests/virbuftest.c index 01db313..2f94e1c 100644 --- a/tests/virbuftest.c +++ b/tests/virbuftest.c
@@ -63,6 +58,77 @@ out: return ret; }
+static int testBufAutoIndent(const void *data ATTRIBUTE_UNUSED) +{ + virBuffer bufinit = VIR_BUFFER_INITIALIZER; + virBufferPtr buf =&bufinit; + const char expected[] = + " 1\n 2\n 3\n 4\n 5\n 6\n 7\n&\n 8\n 9\n"; + char *result = NULL; + int ret = 0; + + if (virBufferGetIndent(buf, false) != 0 || + virBufferGetIndent(buf, true) != 0) { + TEST_ERROR("Wrong indentation"); + ret = -1; + } + virBufferAdjustIndent(buf, 3); + if (virBufferGetIndent(buf, false) != 3 || + virBufferGetIndent(buf, true) != 3 || + virBufferError(buf)) { + TEST_ERROR("Wrong indentation"); + ret = -1; + } + virBufferAdjustIndent(buf, -2); + if (virBufferGetIndent(buf, false) != 1 || + virBufferGetIndent(buf, true) != 1 || + virBufferError(buf)) { + TEST_ERROR("Wrong indentation"); + ret = -1; + } So now buf->indent is 1. Go to the next step, the indent is given -2 again, see what will happen. if virBufferAdjustIndent failed to check the indent overflow, the buf->indent will be -1,too, so it may avoid the check (virBufferGetIndent(buf, false) != -1) and (virBufferGetIndent(buf,
This email is just for your attention. I'm relatively new to work in a community, so I didn't pay much attention to the readability of the comments last email. It seems comments lie in a large patch like this is easily to be omitted. So I cut the codes, leave codes associated with the comments. true) != -1).
+ virBufferAdjustIndent(buf, -2); So I think -3 may be better. + if (virBufferGetIndent(buf, false) != -1 || + virBufferGetIndent(buf, true) != -1 || + virBufferError(buf) != -1) { + TEST_ERROR("Usage error not flagged"); + ret = -1; + } + virBufferFreeAndReset(buf); + if (virBufferGetIndent(buf, false) != 0 || + virBufferGetIndent(buf, true) != 0 || + virBufferError(buf)) { + TEST_ERROR("Reset didn't clear indentation"); + ret = -1; + } + virBufferAdjustIndent(buf, 2); + virBufferAddLit(buf, "1"); + if (virBufferGetIndent(buf, false) != 2 || + virBufferGetIndent(buf, true) != 0) { + TEST_ERROR("Wrong indentation"); + ret = -1; + } + virBufferAddLit(buf, "\n"); + virBufferAdd(buf, "" "2\n", -1); /* Extra "" appeases syntax-check */ + virBufferAddChar(buf, '3'); + virBufferAddChar(buf, '\n'); + virBufferAsprintf(buf, "%d", 4); + virBufferAsprintf(buf, "%c", '\n'); + virBufferStrcat(buf, "5", "\n", "6\n", NULL); + virBufferEscapeString(buf, "%s\n", "7"); + virBufferEscapeString(buf, "%s\n", "&"); + virBufferEscapeSexpr(buf, "%s", "8\n"); + virBufferURIEncodeString(buf, "9"); + virBufferAddChar(buf, '\n'); + + result = virBufferContentAndReset(buf); + if (!result || STRNEQ(result, expected)) { + virtTestDifference(stderr, expected, result); + ret = -1; + } + VIR_FREE(result); + return ret; +} + static int mymain(void) {

On 10/19/2011 08:31 PM, Hai Dong Li wrote:
This email is just for your attention. I'm relatively new to work in a community, so I didn't pay much attention to the readability of the comments last email. It seems comments lie in a large patch like this is easily to be omitted. So I cut the codes, leave codes associated with the comments.
Yes, trimming to just relevant context is a must for any high-volume patch list. Also, separate your replies from the quoted material by blank lines, so it stands out better (visually, I find it easier to spot replies that appear in isolation, by scanning just the left column; not to mention that some mailers corrupt long lines on quoted replies where a long single-line paragraph in the original turns into a wrapped multi-line text with the first line quoted but subsequent lines unquoted; adding whitespace before your reply makes it obvious that you made the comment, rather than your mailer reformatting things).
+ virBufferAdjustIndent(buf, -2); + if (virBufferGetIndent(buf, false) != 1 || + virBufferGetIndent(buf, true) != 1 || + virBufferError(buf)) { + TEST_ERROR("Wrong indentation"); + ret = -1; + } So now buf->indent is 1. Go to the next step, the indent is given -2 again, see what will happen. if virBufferAdjustIndent failed to check the indent overflow, the buf->indent will be -1,too, so it may avoid the check (virBufferGetIndent(buf, false) != -1) and (virBufferGetIndent(buf, true) != -1). + virBufferAdjustIndent(buf, -2); So I think -3 may be better.
Good idea; I've folded that into my patch. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On 10/21/2011 05:35 AM, Eric Blake wrote:
On 10/19/2011 08:31 PM, Hai Dong Li wrote:
This email is just for your attention. I'm relatively new to work in a community, so I didn't pay much attention to the readability of the comments last email. It seems comments lie in a large patch like this is easily to be omitted. So I cut the codes, leave codes associated with the comments.
Yes, trimming to just relevant context is a must for any high-volume patch list. Also, separate your replies from the quoted material by blank lines, so it stands out better (visually, I find it easier to spot replies that appear in isolation, by scanning just the left column; not to mention that some mailers corrupt long lines on quoted replies where a long single-line paragraph in the original turns into a wrapped multi-line text with the first line quoted but subsequent lines unquoted; adding whitespace before your reply makes it obvious that you made the comment, rather than your mailer reformatting things).
Yeh, I think I encountered that when trying to follow threads in an email archive file. Thanks for your advice.
+ virBufferAdjustIndent(buf, -2); + if (virBufferGetIndent(buf, false) != 1 || + virBufferGetIndent(buf, true) != 1 || + virBufferError(buf)) { + TEST_ERROR("Wrong indentation"); + ret = -1; + } So now buf->indent is 1. Go to the next step, the indent is given -2 again, see what will happen. if virBufferAdjustIndent failed to check the indent overflow, the buf->indent will be -1,too, so it may avoid the check (virBufferGetIndent(buf, false) != -1) and (virBufferGetIndent(buf, true) != -1). + virBufferAdjustIndent(buf, -2); So I think -3 may be better.
Good idea; I've folded that into my patch.

<domainsnapshot> is the first public instance of <domain> being used as a sub-element, although we have two other private uses (runtime state, and migration cookie). Although indentation has no effect on XML parsing, using it makes the output more consistent. This uses virBuffer auto-indentation to obtain the effect, for all but the portions of <domain> that are not generated a line at a time into the same virBuffer. Further patches will clean up the remaining problems. * src/conf/domain_conf.h (virDomainDefFormatInternal): New prototype. * src/conf/domain_conf.c (virDomainDefFormatInternal): Export. (virDomainObjFormat, virDomainSnapshotDefFormat): Update callers. * src/libvirt_private.syms (domain_conf.h): Add new export. * src/qemu/qemu_migration.c (qemuMigrationCookieXMLFormat): Use new function. (qemuMigrationCookieXMLFormatStr): Update caller. --- src/conf/domain_conf.c | 16 +++++++++++----- src/conf/domain_conf.h | 3 +++ src/libvirt_private.syms | 1 + src/qemu/qemu_migration.c | 25 ++++++++++++++++--------- 4 files changed, 31 insertions(+), 14 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index c141982..33482c0 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -10483,14 +10483,13 @@ verify(((VIR_DOMAIN_XML_INTERNAL_STATUS | /* This internal version can accept VIR_DOMAIN_XML_INTERNAL_*, * whereas the public version cannot. Also, it appends to an existing - * buffer, rather than flattening to string. Return -1 on failure. */ -static int + * buffer (possibly with auto-indent), rather than flattening to string. + * Return -1 on failure. */ +int virDomainDefFormatInternal(virDomainDefPtr def, unsigned int flags, virBufferPtr buf) { - /* XXX Also need to take an indentation parameter - either int or - * string prefix, so that snapshot xml gets uniform indentation. */ unsigned char *uuid; char uuidstr[VIR_UUID_STRING_BUFLEN]; const char *type = NULL; @@ -10980,8 +10979,10 @@ static char *virDomainObjFormat(virCapsPtr caps, ((caps->privateDataXMLFormat)(&buf, obj->privateData)) < 0) goto error; + virBufferAdjustIndent(&buf, 2); if (virDomainDefFormatInternal(obj->def, flags, &buf) < 0) goto error; + virBufferAdjustIndent(&buf, -2); virBufferAddLit(&buf, "</domstatus>\n"); @@ -11996,7 +11997,12 @@ char *virDomainSnapshotDefFormat(char *domain_uuid, virBufferAddLit(&buf, " </disks>\n"); } if (def->dom) { - virDomainDefFormatInternal(def->dom, flags, &buf); + virBufferAdjustIndent(&buf, 2); + if (virDomainDefFormatInternal(def->dom, flags, &buf) < 0) { + virBufferFreeAndReset(&buf); + return NULL; + } + virBufferAdjustIndent(&buf, -2); } else { virBufferAddLit(&buf, " <domain>\n"); virBufferAsprintf(&buf, " <uuid>%s</uuid>\n", domain_uuid); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 0bc0042..effc630 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1653,6 +1653,9 @@ int virDomainDefAddImplicitControllers(virDomainDefPtr def); char *virDomainDefFormat(virDomainDefPtr def, unsigned int flags); +int virDomainDefFormatInternal(virDomainDefPtr def, + unsigned int flags, + virBufferPtr buf); int virDomainCpuSetParse(const char **str, char sep, diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 695ff33..89cd6da 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -265,6 +265,7 @@ virDomainDefCheckABIStability; virDomainDefClearDeviceAliases; virDomainDefClearPCIAddresses; virDomainDefFormat; +virDomainDefFormatInternal; virDomainDefFree; virDomainDefParseFile; virDomainDefParseNode; diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 1122dab..513ec37 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -378,12 +378,12 @@ static void qemuMigrationCookieGraphicsXMLFormat(virBufferPtr buf, } -static void qemuMigrationCookieXMLFormat(virBufferPtr buf, - qemuMigrationCookiePtr mig) +static int +qemuMigrationCookieXMLFormat(virBufferPtr buf, + qemuMigrationCookiePtr mig) { char uuidstr[VIR_UUID_STRING_BUFLEN]; char hostuuidstr[VIR_UUID_STRING_BUFLEN]; - char *domXML; int i; virUUIDFormat(mig->uuid, uuidstr); @@ -416,14 +416,17 @@ static void qemuMigrationCookieXMLFormat(virBufferPtr buf, if ((mig->flags & QEMU_MIGRATION_COOKIE_PERSISTENT) && mig->persistent) { - domXML = virDomainDefFormat(mig->persistent, - VIR_DOMAIN_XML_INACTIVE | - VIR_DOMAIN_XML_SECURE); - virBufferAdd(buf, domXML, -1); - VIR_FREE(domXML); + virBufferAdjustIndent(buf, 2); + if (virDomainDefFormatInternal(mig->persistent, + VIR_DOMAIN_XML_INACTIVE | + VIR_DOMAIN_XML_SECURE, + buf) < 0) + return -1; + virBufferAdjustIndent(buf, -2); } virBufferAddLit(buf, "</qemu-migration>\n"); + return 0; } @@ -431,10 +434,14 @@ static char *qemuMigrationCookieXMLFormatStr(qemuMigrationCookiePtr mig) { virBuffer buf = VIR_BUFFER_INITIALIZER; - qemuMigrationCookieXMLFormat(&buf, mig); + if (qemuMigrationCookieXMLFormat(&buf, mig) < 0) { + virBufferFreeAndReset(&buf); + return NULL; + } if (virBufferError(&buf)) { virReportOOMError(); + virBufferFreeAndReset(&buf); return NULL; } -- 1.7.4.4

<domainsnapshot> is the first public instance of<domain> being used as a sub-element, although we have two other private uses (runtime state, and migration cookie). Although indentation has no effect on XML parsing, using it makes the output more consistent.
This uses virBuffer auto-indentation to obtain the effect, for all but the portions of<domain> that are not generated a line at a time into the same virBuffer. Further patches will clean up the remaining problems.
* src/conf/domain_conf.h (virDomainDefFormatInternal): New prototype. * src/conf/domain_conf.c (virDomainDefFormatInternal): Export. (virDomainObjFormat, virDomainSnapshotDefFormat): Update callers. * src/libvirt_private.syms (domain_conf.h): Add new export. * src/qemu/qemu_migration.c (qemuMigrationCookieXMLFormat): Use new function. (qemuMigrationCookieXMLFormatStr): Update caller. --- src/conf/domain_conf.c | 16 +++++++++++----- src/conf/domain_conf.h | 3 +++ src/libvirt_private.syms | 1 + src/qemu/qemu_migration.c | 25 ++++++++++++++++--------- 4 files changed, 31 insertions(+), 14 deletions(-)
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 1122dab..513ec37 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -416,14 +416,17 @@ static void qemuMigrationCookieXMLFormat(virBufferPtr buf,
if ((mig->flags& QEMU_MIGRATION_COOKIE_PERSISTENT)&& mig->persistent) { - domXML = virDomainDefFormat(mig->persistent, - VIR_DOMAIN_XML_INACTIVE | - VIR_DOMAIN_XML_SECURE); - virBufferAdd(buf, domXML, -1); Saves one big strlen(). - VIR_FREE(domXML);
@@ -431,10 +434,14 @@ static char *qemuMigrationCookieXMLFormatStr(qemuMigrationCookiePtr mig) { virBuffer buf = VIR_BUFFER_INITIALIZER;
- qemuMigrationCookieXMLFormat(&buf, mig); + if (qemuMigrationCookieXMLFormat(&buf, mig)< 0) { + virBufferFreeAndReset(&buf); + return NULL; + }
if (virBufferError(&buf)) { virReportOOMError(); + virBufferFreeAndReset(&buf); Probably shouldn't be necessary as the virBufferSetError already frees
Dňa 29.9.2011 18:22, Eric Blake wrote / napísal(a): the internal buffer.
return NULL; }
ACK, Peter.

On 10/20/2011 03:08 AM, Peter Krempa wrote:
<domainsnapshot> is the first public instance of<domain> being used as a sub-element, although we have two other private uses (runtime state, and migration cookie). Although indentation has no effect on XML parsing, using it makes the output more consistent.
This uses virBuffer auto-indentation to obtain the effect, for all but the portions of<domain> that are not generated a line at a time into the same virBuffer. Further patches will clean up the remaining problems.
* src/conf/domain_conf.h (virDomainDefFormatInternal): New prototype. * src/conf/domain_conf.c (virDomainDefFormatInternal): Export. (virDomainObjFormat, virDomainSnapshotDefFormat): Update callers. * src/libvirt_private.syms (domain_conf.h): Add new export. * src/qemu/qemu_migration.c (qemuMigrationCookieXMLFormat): Use new function. (qemuMigrationCookieXMLFormatStr): Update caller. --- src/conf/domain_conf.c | 16 +++++++++++----- src/conf/domain_conf.h | 3 +++ src/libvirt_private.syms | 1 + src/qemu/qemu_migration.c | 25 ++++++++++++++++--------- 4 files changed, 31 insertions(+), 14 deletions(-)
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 1122dab..513ec37 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -416,14 +416,17 @@ static void qemuMigrationCookieXMLFormat(virBufferPtr buf,
if ((mig->flags& QEMU_MIGRATION_COOKIE_PERSISTENT)&& mig->persistent) { - domXML = virDomainDefFormat(mig->persistent, - VIR_DOMAIN_XML_INACTIVE | - VIR_DOMAIN_XML_SECURE); - virBufferAdd(buf, domXML, -1); Saves one big strlen(). Yeah, hundreds of bytes at least. - VIR_FREE(domXML);
@@ -431,10 +434,14 @@ static char *qemuMigrationCookieXMLFormatStr(qemuMigrationCookiePtr mig) { virBuffer buf = VIR_BUFFER_INITIALIZER;
- qemuMigrationCookieXMLFormat(&buf, mig); + if (qemuMigrationCookieXMLFormat(&buf, mig)< 0) { + virBufferFreeAndReset(&buf); + return NULL; + }
if (virBufferError(&buf)) { virReportOOMError(); + virBufferFreeAndReset(&buf); Probably shouldn't be necessary as the virBufferSetError already frees
Dňa 29.9.2011 18:22, Eric Blake wrote / napísal(a): the internal buffer. Maybe for sure. Relying on other function's error handling(especially when it is a deep calling line) is a little not that sure.
return NULL; }
ACK,
Peter.
-- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list

On 10/19/2011 10:04 PM, Hai Dong Li wrote:
On 10/20/2011 03:08 AM, Peter Krempa wrote:
Dňa 29.9.2011 18:22, Eric Blake wrote / napísal(a):
<domainsnapshot> is the first public instance of<domain> being used as a sub-element, although we have two other private uses (runtime state, and migration cookie). Although indentation has no effect on XML parsing, using it makes the output more consistent.
@@ -431,10 +434,14 @@ static char *qemuMigrationCookieXMLFormatStr(qemuMigrationCookiePtr mig) { virBuffer buf = VIR_BUFFER_INITIALIZER;
- qemuMigrationCookieXMLFormat(&buf, mig); + if (qemuMigrationCookieXMLFormat(&buf, mig)< 0) { + virBufferFreeAndReset(&buf); + return NULL; + }
if (virBufferError(&buf)) { virReportOOMError(); + virBufferFreeAndReset(&buf); Probably shouldn't be necessary as the virBufferSetError already frees the internal buffer. Maybe for sure. Relying on other function's error handling(especially when it is a deep calling line) is a little not that sure.
Peter's right that it wasn't strictly necessary, given the fact that any OOM error with virBuffer frees memory at that point, so there is nothing further to free here. And Hai's right that relying on an obscure feature of the current implementation of the called function is harder to maintain than explicitly cleaning up after ourselves here, even if our cleanup happens to be a no-op due to the called function. I kept this line as-is, considering that the failure case is unexpected in the first place, so the efficiency of avoiding a no-op is much less important than robustness if the virBuffer implementation changes in the future.
return NULL; } ACK,
Now pushed. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

Add a test for the simple parts of my indentation changes, and fix the fallout. * tests/domainsnapshotxml2xmltest.c: New test. * tests/Makefile.am (domainsnapshotxml2xmltest_SOURCES): Build it. * src/conf/domain_conf.c (virDomainSnapshotDefFormat): Avoid NULL deref, match documented order. * src/conf/domain_conf.h (virDomainSnapshotDefFormat): Add const. * tests/domainsnapshotxml2xmlout/all_parameters.xml: Tweak output. * tests/domainsnapshotxml2xmlout/disk_snapshot.xml: Likewise. * tests/domainsnapshotxml2xmlout/full_domain.xml: Likewise. * .gitignore: Exempt new binary. --- .gitignore | 1 + src/conf/domain_conf.c | 10 +- src/conf/domain_conf.h | 2 +- tests/Makefile.am | 14 ++- tests/domainsnapshotxml2xmlout/all_parameters.xml | 2 +- tests/domainsnapshotxml2xmlout/disk_snapshot.xml | 102 ++++++++-------- tests/domainsnapshotxml2xmlout/full_domain.xml | 52 ++++---- tests/domainsnapshotxml2xmltest.c | 128 +++++++++++++++++++++ 8 files changed, 224 insertions(+), 87 deletions(-) create mode 100644 tests/domainsnapshotxml2xmltest.c diff --git a/.gitignore b/.gitignore index 41fa50f..bfe8e87 100644 --- a/.gitignore +++ b/.gitignore @@ -69,6 +69,7 @@ /src/util/virkeymaps.h /tests/*.log /tests/cputest +/tests/domainsnapshotxml2xmltest /tests/hashtest /tests/jsontest /tests/networkxml2argvtest diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 33482c0..0b82c3d 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -11942,7 +11942,7 @@ cleanup: return ret; } -char *virDomainSnapshotDefFormat(char *domain_uuid, +char *virDomainSnapshotDefFormat(const char *domain_uuid, virDomainSnapshotDefPtr def, unsigned int flags, int internal) @@ -11983,12 +11983,12 @@ char *virDomainSnapshotDefFormat(char *domain_uuid, virDomainDiskSnapshotTypeToString(disk->snapshot)); if (disk->file || disk->driverType) { virBufferAddLit(&buf, ">\n"); - if (disk->file) - virBufferEscapeString(&buf, " <source file='%s'/>\n", - disk->file); if (disk->driverType) virBufferEscapeString(&buf, " <driver type='%s'/>\n", disk->driverType); + if (disk->file) + virBufferEscapeString(&buf, " <source file='%s'/>\n", + disk->file); virBufferAddLit(&buf, " </disk>\n"); } else { virBufferAddLit(&buf, "/>\n"); @@ -12003,7 +12003,7 @@ char *virDomainSnapshotDefFormat(char *domain_uuid, return NULL; } virBufferAdjustIndent(&buf, -2); - } else { + } else if (domain_uuid) { virBufferAddLit(&buf, " <domain>\n"); virBufferAsprintf(&buf, " <uuid>%s</uuid>\n", domain_uuid); virBufferAddLit(&buf, " </domain>\n"); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index effc630..4126d58 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1472,7 +1472,7 @@ virDomainSnapshotDefPtr virDomainSnapshotDefParseString(const char *xmlStr, unsigned int expectedVirtTypes, unsigned int flags); void virDomainSnapshotDefFree(virDomainSnapshotDefPtr def); -char *virDomainSnapshotDefFormat(char *domain_uuid, +char *virDomainSnapshotDefFormat(const char *domain_uuid, virDomainSnapshotDefPtr def, unsigned int flags, int internal); diff --git a/tests/Makefile.am b/tests/Makefile.am index cbbbc6f..4769fa5 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -102,7 +102,8 @@ check_PROGRAMS += xml2sexprtest sexpr2xmltest \ xmconfigtest xencapstest statstest reconnect endif if WITH_QEMU -check_PROGRAMS += qemuxml2argvtest qemuxml2xmltest qemuargv2xmltest qemuhelptest +check_PROGRAMS += qemuxml2argvtest qemuxml2xmltest qemuargv2xmltest \ + qemuhelptest domainsnapshotxml2xmltest endif if WITH_OPENVZ @@ -228,7 +229,7 @@ endif if WITH_QEMU TESTS += qemuxml2argvtest qemuxml2xmltest qemuargv2xmltest qemuhelptest -TESTS += nwfilterxml2xmltest +TESTS += domainsnapshotxml2xmltest nwfilterxml2xmltest endif if WITH_OPENVZ @@ -350,8 +351,15 @@ qemuargv2xmltest_LDADD = $(qemu_LDADDS) $(LDADDS) qemuhelptest_SOURCES = qemuhelptest.c testutils.c testutils.h qemuhelptest_LDADD = $(qemu_LDADDS) $(LDADDS) + +domainsnapshotxml2xmltest_SOURCES = \ + domainsnapshotxml2xmltest.c testutilsqemu.c testutilsqemu.h \ + testutils.c testutils.h +domainsnapshotxml2xmltest_LDADD = $(qemu_LDADDS) $(LDADDS) else -EXTRA_DIST += qemuxml2argvtest.c qemuxml2xmltest.c qemuargv2xmltest.c qemuhelptest.c testutilsqemu.c testutilsqemu.h +EXTRA_DIST += qemuxml2argvtest.c qemuxml2xmltest.c qemuargv2xmltest.c \ + qemuhelptest.c domainsnapshotxml2xmltest.c \ + testutilsqemu.c testutilsqemu.h endif if WITH_OPENVZ diff --git a/tests/domainsnapshotxml2xmlout/all_parameters.xml b/tests/domainsnapshotxml2xmlout/all_parameters.xml index ed4a600..eb2ee85 100644 --- a/tests/domainsnapshotxml2xmlout/all_parameters.xml +++ b/tests/domainsnapshotxml2xmlout/all_parameters.xml @@ -1,10 +1,10 @@ <domainsnapshot> <name>my snap name</name> <description>!@#$%^</description> + <state>running</state> <parent> <name>earlier_snap</name> </parent> - <state>running</state> <creationTime>1272917631</creationTime> <domain> <uuid>9d37b878-a7cc-9f9a-b78f-49b3abad25a8</uuid> diff --git a/tests/domainsnapshotxml2xmlout/disk_snapshot.xml b/tests/domainsnapshotxml2xmlout/disk_snapshot.xml index e0414a1..a0a0965 100644 --- a/tests/domainsnapshotxml2xmlout/disk_snapshot.xml +++ b/tests/domainsnapshotxml2xmlout/disk_snapshot.xml @@ -1,10 +1,10 @@ <domainsnapshot> <name>my snap name</name> <description>!@#$%^</description> + <state>disk-snapshot</state> <parent> <name>earlier_snap</name> </parent> - <state>disk-snapshot</state> <creationTime>1272917631</creationTime> <disks> <disk name='hda' snapshot='no'/> @@ -23,55 +23,55 @@ <source file='/path/to/generated5'/> </disk> </disks> -<domain type='qemu'> - <name>QEMUGuest1</name> - <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> - <memory>219100</memory> - <currentMemory>219100</currentMemory> - <vcpu cpuset='1-4,8-20,525'>1</vcpu> - <os> - <type arch='i686' machine='pc'>hvm</type> - <boot dev='hd'/> - </os> - <clock offset='utc'/> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>destroy</on_crash> - <devices> - <emulator>/usr/bin/qemu</emulator> - <disk type='block' device='disk'> - <source dev='/dev/HostVG/QEMUGuest1'/> - <target dev='hda' bus='ide'/> - <address type='drive' controller='0' bus='0' unit='0'/> - </disk> - <disk type='block' device='disk'> - <source dev='/dev/HostVG/QEMUGuest2'/> - <target dev='hdb' bus='ide'/> - <address type='drive' controller='0' bus='1' unit='0'/> - </disk> - <disk type='block' device='disk'> - <source dev='/dev/HostVG/QEMUGuest3'/> - <target dev='hdc' bus='ide'/> - <address type='drive' controller='0' bus='2' unit='0'/> - </disk> - <disk type='block' device='disk'> - <source dev='/dev/HostVG/QEMUGuest4'/> - <target dev='hdd' bus='ide'/> - <address type='drive' controller='0' bus='3' unit='0'/> - </disk> - <disk type='block' device='disk'> - <source dev='/dev/HostVG/QEMUGuest5'/> - <target dev='hde' bus='ide'/> - <address type='drive' controller='0' bus='4' unit='0'/> - </disk> - <disk type='block' device='disk'> - <source dev='/dev/HostVG/QEMUGuest6'/> - <target dev='hdf' bus='ide'/> - <address type='drive' controller='0' bus='5' unit='0'/> - </disk> - <controller type='ide' index='0'/> - <memballoon model='virtio'/> - </devices> -</domain> + <domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory>219100</memory> + <currentMemory>219100</currentMemory> + <vcpu cpuset='1-4,8-20,525'>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu</emulator> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' unit='0'/> + </disk> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest2'/> + <target dev='hdb' bus='ide'/> + <address type='drive' controller='0' bus='1' unit='0'/> + </disk> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest3'/> + <target dev='hdc' bus='ide'/> + <address type='drive' controller='0' bus='2' unit='0'/> + </disk> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest4'/> + <target dev='hdd' bus='ide'/> + <address type='drive' controller='0' bus='3' unit='0'/> + </disk> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest5'/> + <target dev='hde' bus='ide'/> + <address type='drive' controller='0' bus='4' unit='0'/> + </disk> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest6'/> + <target dev='hdf' bus='ide'/> + <address type='drive' controller='0' bus='5' unit='0'/> + </disk> + <controller type='ide' index='0'/> + <memballoon model='virtio'/> + </devices> + </domain> <active>1</active> </domainsnapshot> diff --git a/tests/domainsnapshotxml2xmlout/full_domain.xml b/tests/domainsnapshotxml2xmlout/full_domain.xml index 942bd7f..76f17e1 100644 --- a/tests/domainsnapshotxml2xmlout/full_domain.xml +++ b/tests/domainsnapshotxml2xmlout/full_domain.xml @@ -1,35 +1,35 @@ <domainsnapshot> <name>my snap name</name> <description>!@#$%^</description> + <state>running</state> <parent> <name>earlier_snap</name> </parent> - <state>running</state> <creationTime>1272917631</creationTime> -<domain type='qemu'> - <name>QEMUGuest1</name> - <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> - <memory>219100</memory> - <currentMemory>219100</currentMemory> - <vcpu cpuset='1-4,8-20,525'>1</vcpu> - <os> - <type arch='i686' machine='pc'>hvm</type> - <boot dev='hd'/> - </os> - <clock offset='utc'/> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>destroy</on_crash> - <devices> - <emulator>/usr/bin/qemu</emulator> - <disk type='block' device='disk'> - <source dev='/dev/HostVG/QEMUGuest1'/> - <target dev='hda' bus='ide'/> - <address type='drive' controller='0' bus='0' unit='0'/> - </disk> - <controller type='ide' index='0'/> - <memballoon model='virtio'/> - </devices> -</domain> + <domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory>219100</memory> + <currentMemory>219100</currentMemory> + <vcpu cpuset='1-4,8-20,525'>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu</emulator> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' unit='0'/> + </disk> + <controller type='ide' index='0'/> + <memballoon model='virtio'/> + </devices> + </domain> <active>1</active> </domainsnapshot> diff --git a/tests/domainsnapshotxml2xmltest.c b/tests/domainsnapshotxml2xmltest.c new file mode 100644 index 0000000..c2266f4 --- /dev/null +++ b/tests/domainsnapshotxml2xmltest.c @@ -0,0 +1,128 @@ +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + +#include <sys/types.h> +#include <fcntl.h> + +#ifdef WITH_QEMU + +# include "internal.h" +# include "testutils.h" +# include "qemu/qemu_conf.h" +# include "qemu/qemu_domain.h" +# include "testutilsqemu.h" + +static struct qemud_driver driver; + +static int +testCompareXMLToXMLFiles(const char *inxml, const char *uuid, int internal) +{ + char *inXmlData = NULL; + char *actual = NULL; + int ret = -1; + virDomainSnapshotDefPtr def = NULL; + unsigned int flags = (VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE | + VIR_DOMAIN_SNAPSHOT_PARSE_DISKS); + + if (virtTestLoadFile(inxml, &inXmlData) < 0) + goto fail; + + if (internal) + flags |= VIR_DOMAIN_SNAPSHOT_PARSE_INTERNAL; + if (!(def = virDomainSnapshotDefParseString(inXmlData, driver.caps, + QEMU_EXPECTED_VIRT_TYPES, + flags))) + goto fail; + + if (!(actual = virDomainSnapshotDefFormat(uuid, def, + VIR_DOMAIN_XML_SECURE, + internal))) + goto fail; + + + if (STRNEQ(inXmlData, actual)) { + virtTestDifference(stderr, inXmlData, actual); + goto fail; + } + + ret = 0; + fail: + free(inXmlData); + free(actual); + virDomainSnapshotDefFree(def); + return ret; +} + +struct testInfo { + const char *name; + const char *uuid; + int internal; +}; + +static int +testCompareXMLToXMLHelper(const void *data) +{ + const struct testInfo *info = data; + char *xml_in = NULL; + int ret = -1; + + if (virAsprintf(&xml_in, "%s/domainsnapshotxml2xmlout/%s.xml", + abs_srcdir, info->name) < 0) + goto cleanup; + + ret = testCompareXMLToXMLFiles(xml_in, info->uuid, info->internal); + +cleanup: + free(xml_in); + return ret; +} + + +static int +mymain(void) +{ + int ret = 0; + + if ((driver.caps = testQemuCapsInit()) == NULL) + return (EXIT_FAILURE); + +# define DO_TEST(name, uuid, internal) \ + do { \ + const struct testInfo info = {name, uuid, internal}; \ + if (virtTestRun("SNAPSHOT XML-2-XML " name, \ + 1, testCompareXMLToXMLHelper, &info) < 0) \ + ret = -1; \ + } while (0) + + /* Unset or set all envvars here that are copied in qemudBuildCommandLine + * using ADD_ENV_COPY, otherwise these tests may fail due to unexpected + * values for these envvars */ + setenv("PATH", "/bin", 1); + + DO_TEST("all_parameters", "9d37b878-a7cc-9f9a-b78f-49b3abad25a8", 1); + DO_TEST("disk_snapshot", "c7a5fdbd-edaf-9455-926a-d65c16db1809", 1); + DO_TEST("full_domain", "c7a5fdbd-edaf-9455-926a-d65c16db1809", 1); + DO_TEST("noparent_nodescription_noactive", NULL, 0); + DO_TEST("noparent_nodescription", NULL, 1); + DO_TEST("noparent", "9d37b878-a7cc-9f9a-b78f-49b3abad25a8", 0); + + virCapabilitiesFree(driver.caps); + + return (ret==0 ? EXIT_SUCCESS : EXIT_FAILURE); +} + +VIRT_TEST_MAIN(mymain) + +#else + +int +main(void) +{ + return EXIT_AM_SKIP; +} + +#endif /* WITH_QEMU */ -- 1.7.4.4

On 09/30/2011 12:22 AM, Eric Blake wrote:
diff --git a/tests/domainsnapshotxml2xmlout/all_parameters.xml b/tests/domainsnapshotxml2xmlout/all_parameters.xml index ed4a600..eb2ee85 100644 --- a/tests/domainsnapshotxml2xmlout/all_parameters.xml +++ b/tests/domainsnapshotxml2xmlout/all_parameters.xml @@ -1,10 +1,10 @@ <domainsnapshot> <name>my snap name</name> <description>!@#$%^</description> +<state>running</state> I failed to see why this line is moved here. The definition of struct _virDomainSnapshotDef shows that the member state is after the member creationTime. Could you please let me know the sorting order? <parent> <name>earlier_snap</name> </parent> -<state>running</state> <creationTime>1272917631</creationTime> <domain> <uuid>9d37b878-a7cc-9f9a-b78f-49b3abad25a8</uuid>

On 10/20/2011 01:23 AM, Hai Dong Li wrote:
On 09/30/2011 12:22 AM, Eric Blake wrote:
diff --git a/tests/domainsnapshotxml2xmlout/all_parameters.xml b/tests/domainsnapshotxml2xmlout/all_parameters.xml index ed4a600..eb2ee85 100644 --- a/tests/domainsnapshotxml2xmlout/all_parameters.xml +++ b/tests/domainsnapshotxml2xmlout/all_parameters.xml @@ -1,10 +1,10 @@ <domainsnapshot> <name>my snap name</name> <description>!@#$%^</description> +<state>running</state> I failed to see why this line is moved here. The definition of struct _virDomainSnapshotDef shows that the member state is after the member creationTime. Could you please let me know the sorting order?
Previously, the test was useful only for schema validation of input, and our schema allows elements to be interleaved in any order. But now that we are adding a test of our XML generation matching expected output, then this file has to match what we generate (domain_conf.c virDomainSnapshotDefFormat). Besides, our documentation already mentioned <state> before <parent> (docs/formatsnapshot.html.in). On 10/20/2011 03:00 AM, Peter Krempa wrote:
Dňa 29.9.2011 18:22, Eric Blake wrote / napísal(a):
Add a test for the simple parts of my indentation changes, and fix the fallout.
* tests/domainsnapshotxml2xmltest.c: New test. * tests/Makefile.am (domainsnapshotxml2xmltest_SOURCES): Build it. * src/conf/domain_conf.c (virDomainSnapshotDefFormat): Avoid NULL deref, match documented order. * src/conf/domain_conf.h (virDomainSnapshotDefFormat): Add const. * tests/domainsnapshotxml2xmlout/all_parameters.xml: Tweak output. * tests/domainsnapshotxml2xmlout/disk_snapshot.xml: Likewise. * tests/domainsnapshotxml2xmlout/full_domain.xml: Likewise. * .gitignore: Exempt new binary. ---
Definitely looks nicer when correctly indented. ACK.
Pushed. I also had to rebase this one on top of recent test changes. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

Dňa 29.9.2011 18:22, Eric Blake wrote / napísal(a):
Add a test for the simple parts of my indentation changes, and fix the fallout.
* tests/domainsnapshotxml2xmltest.c: New test. * tests/Makefile.am (domainsnapshotxml2xmltest_SOURCES): Build it. * src/conf/domain_conf.c (virDomainSnapshotDefFormat): Avoid NULL deref, match documented order. * src/conf/domain_conf.h (virDomainSnapshotDefFormat): Add const. * tests/domainsnapshotxml2xmlout/all_parameters.xml: Tweak output. * tests/domainsnapshotxml2xmlout/disk_snapshot.xml: Likewise. * tests/domainsnapshotxml2xmlout/full_domain.xml: Likewise. * .gitignore: Exempt new binary. ---
Definitely looks nicer when correctly indented. ACK. Peter

The improvements to virBuffer, along with a paradigm shift to pass the original buffer through rather than creating a second buffer, allow us to shave off quite a few lines of code. * src/util/sysinfo.h (virSysinfoFormat): Alter signature. * src/util/sysinfo.c (virSysinfoFormat, virSysinfoBIOSFormat) (virSysinfoSystemFormat, virSysinfoProcessorFormat) (virSysinfoMemoryFormat): Change indentation parameter. * src/conf/domain_conf.c (virDomainSysinfoDefFormat): Adjust caller. * src/qemu/qemu_driver.c (qemuGetSysinfo): Likewise. --- src/conf/domain_conf.c | 12 +- src/qemu/qemu_driver.c | 9 +- src/util/sysinfo.c | 399 ++++++++++++++++-------------------------------- src/util/sysinfo.h | 3 +- 4 files changed, 147 insertions(+), 276 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 0b82c3d..eb82fa6 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -9897,13 +9897,11 @@ static int virDomainSysinfoDefFormat(virBufferPtr buf, virSysinfoDefPtr def) { - char *format = virSysinfoFormat(def, " "); - - if (!format) - return -1; - virBufferAdd(buf, format, strlen(format)); - VIR_FREE(format); - return 0; + int ret; + virBufferAdjustIndent(buf, 2); + ret = virSysinfoFormat(buf, def); + virBufferAdjustIndent(buf, -2); + return ret; } diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 0f18983..b459b73 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -963,6 +963,7 @@ static char * qemuGetSysinfo(virConnectPtr conn, unsigned int flags) { struct qemud_driver *driver = conn->privateData; + virBuffer buf = VIR_BUFFER_INITIALIZER; virCheckFlags(0, NULL); @@ -972,7 +973,13 @@ qemuGetSysinfo(virConnectPtr conn, unsigned int flags) return NULL; } - return virSysinfoFormat(driver->hostsysinfo, ""); + if (virSysinfoFormat(&buf, driver->hostsysinfo) < 0) + return NULL; + if (virBufferError(&buf)) { + virReportOOMError(); + return NULL; + } + return virBufferContentAndReset(&buf); } static int qemudGetMaxVCPUs(virConnectPtr conn ATTRIBUTE_UNUSED, const char *type) { diff --git a/src/util/sysinfo.c b/src/util/sysinfo.c index 6625cae..de3108a 100644 --- a/src/util/sysinfo.c +++ b/src/util/sysinfo.c @@ -515,324 +515,189 @@ no_memory: #endif /* !WIN32 && x86 */ static void -virSysinfoBIOSFormat(virSysinfoDefPtr def, const char *prefix, - virBufferPtr buf) +virSysinfoBIOSFormat(virBufferPtr buf, virSysinfoDefPtr def) { - int len = strlen(prefix); - - if ((def->bios_vendor != NULL) || (def->bios_version != NULL) || - (def->bios_date != NULL) || (def->bios_release != NULL)) { - virBufferAsprintf(buf, "%s <bios>\n", prefix); - if (def->bios_vendor != NULL) { - virBufferAdd(buf, prefix, len); - virBufferEscapeString(buf, - " <entry name='vendor'>%s</entry>\n", - def->bios_vendor); - } - if (def->bios_version != NULL) { - virBufferAdd(buf, prefix, len); - virBufferEscapeString(buf, - " <entry name='version'>%s</entry>\n", - def->bios_version); - } - if (def->bios_date != NULL) { - virBufferAdd(buf, prefix, len); - virBufferEscapeString(buf, - " <entry name='date'>%s</entry>\n", - def->bios_date); - } - if (def->bios_release != NULL) { - virBufferAdd(buf, prefix, len); - virBufferEscapeString(buf, - " <entry name='release'>%s</entry>\n", - def->bios_release); - } - virBufferAsprintf(buf, "%s </bios>\n", prefix); - } + if (!def->bios_vendor && !def->bios_version && + !def->bios_date && !def->bios_release) + return; - return; + virBufferAddLit(buf, " <bios>\n"); + virBufferEscapeString(buf, " <entry name='vendor'>%s</entry>\n", + def->bios_vendor); + virBufferEscapeString(buf, " <entry name='version'>%s</entry>\n", + def->bios_version); + virBufferEscapeString(buf, " <entry name='date'>%s</entry>\n", + def->bios_date); + virBufferEscapeString(buf, " <entry name='release'>%s</entry>\n", + def->bios_release); + virBufferAddLit(buf, " </bios>\n"); } static void -virSysinfoSystemFormat(virSysinfoDefPtr def, const char *prefix, - virBufferPtr buf) +virSysinfoSystemFormat(virBufferPtr buf, virSysinfoDefPtr def) { - int len = strlen(prefix); - - if ((def->system_manufacturer != NULL) || (def->system_product != NULL) || - (def->system_version != NULL) || (def->system_serial != NULL) || - (def->system_uuid != NULL) || (def->system_sku != NULL) || - (def->system_family != NULL)) { - virBufferAsprintf(buf, "%s <system>\n", prefix); - if (def->system_manufacturer != NULL) { - virBufferAdd(buf, prefix, len); - virBufferEscapeString(buf, - " <entry name='manufacturer'>%s</entry>\n", - def->system_manufacturer); - } - if (def->system_product != NULL) { - virBufferAdd(buf, prefix, len); - virBufferEscapeString(buf, - " <entry name='product'>%s</entry>\n", - def->system_product); - } - if (def->system_version != NULL) { - virBufferAdd(buf, prefix, len); - virBufferEscapeString(buf, - " <entry name='version'>%s</entry>\n", - def->system_version); - } - if (def->system_serial != NULL) { - virBufferAdd(buf, prefix, len); - virBufferEscapeString(buf, - " <entry name='serial'>%s</entry>\n", - def->system_serial); - } - if (def->system_uuid != NULL) { - virBufferAdd(buf, prefix, len); - virBufferEscapeString(buf, - " <entry name='uuid'>%s</entry>\n", - def->system_uuid); - } - if (def->system_sku != NULL) { - virBufferAdd(buf, prefix, len); - virBufferEscapeString(buf, - " <entry name='sku'>%s</entry>\n", - def->system_sku); - } - if (def->system_family != NULL) { - virBufferAdd(buf, prefix, len); - virBufferEscapeString(buf, - " <entry name='family'>%s</entry>\n", - def->system_family); - } - virBufferAsprintf(buf, "%s </system>\n", prefix); - } + if (!def->system_manufacturer && !def->system_product && + !def->system_version && !def->system_serial && + !def->system_uuid && !def->system_sku && !def->system_family) + return; - return; + virBufferAddLit(buf, " <system>\n"); + virBufferEscapeString(buf, " <entry name='manufacturer'>%s</entry>\n", + def->system_manufacturer); + virBufferEscapeString(buf, " <entry name='product'>%s</entry>\n", + def->system_product); + virBufferEscapeString(buf, " <entry name='version'>%s</entry>\n", + def->system_version); + virBufferEscapeString(buf, " <entry name='serial'>%s</entry>\n", + def->system_serial); + virBufferEscapeString(buf, " <entry name='uuid'>%s</entry>\n", + def->system_uuid); + virBufferEscapeString(buf, " <entry name='sku'>%s</entry>\n", + def->system_sku); + virBufferEscapeString(buf, " <entry name='family'>%s</entry>\n", + def->system_family); + virBufferAddLit(buf, " </system>\n"); } static void -virSysinfoProcessorFormat(virSysinfoDefPtr def, const char *prefix, - virBufferPtr buf) +virSysinfoProcessorFormat(virBufferPtr buf, virSysinfoDefPtr def) { int i; - int len = strlen(prefix); virSysinfoProcessorDefPtr processor; for (i = 0; i < def->nprocessor; i++) { processor = &def->processor[i]; - if ((processor->processor_socket_destination != NULL) || - (processor->processor_type != NULL) || - (processor->processor_family != NULL) || - (processor->processor_manufacturer != NULL) || - (processor->processor_signature != NULL) || - (processor->processor_version != NULL) || - (processor->processor_external_clock != NULL) || - (processor->processor_max_speed != NULL) || - (processor->processor_status != NULL) || - (processor->processor_serial_number != NULL) || - (processor->processor_part_number != NULL)) { - virBufferAsprintf(buf, "%s <processor>\n", prefix); - if (processor->processor_socket_destination != NULL) { - virBufferAdd(buf, prefix, len); - virBufferEscapeString(buf, - " <entry name='socket_destination'>%s</entry>\n", - processor->processor_socket_destination); - } - if (processor->processor_type != NULL) { - virBufferAdd(buf, prefix, len); - virBufferEscapeString(buf, - " <entry name='type'>%s</entry>\n", - processor->processor_type); - } - if (processor->processor_family != NULL) { - virBufferAdd(buf, prefix, len); - virBufferEscapeString(buf, - " <entry name='family'>%s</entry>\n", - processor->processor_family); - } - if (processor->processor_manufacturer != NULL) { - virBufferAdd(buf, prefix, len); - virBufferEscapeString(buf, - " <entry name='manufacturer'>%s</entry>\n", - processor->processor_manufacturer); - } - if (processor->processor_signature != NULL) { - virBufferAdd(buf, prefix, len); - virBufferEscapeString(buf, - " <entry name='signature'>%s</entry>\n", - processor->processor_signature); - } - if (processor->processor_version != NULL) { - virBufferAdd(buf, prefix, len); - virBufferEscapeString(buf, - " <entry name='version'>%s</entry>\n", - processor->processor_version); - } - if (processor->processor_external_clock != NULL) { - virBufferAdd(buf, prefix, len); - virBufferEscapeString(buf, - " <entry name='external_clock'>%s</entry>\n", - processor->processor_external_clock); - } - if (processor->processor_max_speed != NULL) { - virBufferAdd(buf, prefix, len); - virBufferEscapeString(buf, - " <entry name='max_speed'>%s</entry>\n", - processor->processor_max_speed); - } - if (processor->processor_status != NULL) { - virBufferAdd(buf, prefix, len); - virBufferEscapeString(buf, - " <entry name='status'>%s</entry>\n", - processor->processor_status); - } - if (processor->processor_serial_number != NULL) { - virBufferAdd(buf, prefix, len); - virBufferEscapeString(buf, - " <entry name='serial_number'>%s</entry>\n", - processor->processor_serial_number); - } - if (processor->processor_part_number != NULL) { - virBufferAdd(buf, prefix, len); - virBufferEscapeString(buf, - " <entry name='part_number'>%s</entry>\n", - processor->processor_part_number); - } - virBufferAsprintf(buf, "%s </processor>\n", prefix); - } + if (!processor->processor_socket_destination && + !processor->processor_type && + !processor->processor_family && + !processor->processor_manufacturer && + !processor->processor_signature && + !processor->processor_version && + !processor->processor_external_clock && + !processor->processor_max_speed && + !processor->processor_status && + !processor->processor_serial_number && + !processor->processor_part_number) + continue; + + virBufferAddLit(buf, " <processor>\n"); + virBufferAdjustIndent(buf, 4); + virBufferEscapeString(buf, + "<entry name='socket_destination'>%s</entry>\n", + processor->processor_socket_destination); + virBufferEscapeString(buf, "<entry name='type'>%s</entry>\n", + processor->processor_type); + virBufferEscapeString(buf, "<entry name='family'>%s</entry>\n", + processor->processor_family); + virBufferEscapeString(buf, "<entry name='manufacturer'>%s</entry>\n", + processor->processor_manufacturer); + virBufferEscapeString(buf, "<entry name='signature'>%s</entry>\n", + processor->processor_signature); + virBufferEscapeString(buf, "<entry name='version'>%s</entry>\n", + processor->processor_version); + virBufferEscapeString(buf, "<entry name='external_clock'>%s</entry>\n", + processor->processor_external_clock); + virBufferEscapeString(buf, "<entry name='max_speed'>%s</entry>\n", + processor->processor_max_speed); + virBufferEscapeString(buf, "<entry name='status'>%s</entry>\n", + processor->processor_status); + virBufferEscapeString(buf, "<entry name='serial_number'>%s</entry>\n", + processor->processor_serial_number); + virBufferEscapeString(buf, "<entry name='part_number'>%s</entry>\n", + processor->processor_part_number); + virBufferAdjustIndent(buf, -4); + virBufferAddLit(buf, " </processor>\n"); } - - return; } static void -virSysinfoMemoryFormat(virSysinfoDefPtr def, const char *prefix, - virBufferPtr buf) +virSysinfoMemoryFormat(virBufferPtr buf, virSysinfoDefPtr def) { int i; - int len = strlen(prefix); virSysinfoMemoryDefPtr memory; for (i = 0; i < def->nmemory; i++) { memory = &def->memory[i]; - if ((memory->memory_size != NULL) || - (memory->memory_form_factor != NULL) || - (memory->memory_locator != NULL) || - (memory->memory_bank_locator != NULL) || - (memory->memory_type != NULL) || - (memory->memory_type_detail != NULL) || - (memory->memory_speed != NULL) || - (memory->memory_manufacturer != NULL) || - (memory->memory_serial_number != NULL) || - (memory->memory_part_number != NULL)) { - virBufferAsprintf(buf, "%s <memory_device>\n", prefix); - if (memory->memory_size != NULL) { - virBufferAdd(buf, prefix, len); - virBufferEscapeString(buf, - " <entry name='size'>%s</entry>\n", - memory->memory_size); - } - if (memory->memory_form_factor != NULL) { - virBufferAdd(buf, prefix, len); - virBufferEscapeString(buf, - " <entry name='form_factor'>%s</entry>\n", - memory->memory_form_factor); - } - if (memory->memory_locator != NULL) { - virBufferAdd(buf, prefix, len); - virBufferEscapeString(buf, - " <entry name='locator'>%s</entry>\n", - memory->memory_locator); - } - if (memory->memory_bank_locator != NULL) { - virBufferAdd(buf, prefix, len); - virBufferEscapeString(buf, - " <entry name='bank_locator'>%s</entry>\n", - memory->memory_bank_locator); - } - if (memory->memory_type != NULL) { - virBufferAdd(buf, prefix, len); - virBufferEscapeString(buf, - " <entry name='type'>%s</entry>\n", - memory->memory_type); - } - if (memory->memory_type_detail != NULL) { - virBufferAdd(buf, prefix, len); - virBufferEscapeString(buf, - " <entry name='type_detail'>%s</entry>\n", - memory->memory_type_detail); - } - if (memory->memory_speed != NULL) { - virBufferAdd(buf, prefix, len); - virBufferEscapeString(buf, - " <entry name='speed'>%s</entry>\n", - memory->memory_speed); - } - if (memory->memory_manufacturer != NULL) { - virBufferAdd(buf, prefix, len); - virBufferEscapeString(buf, - " <entry name='manufacturer'>%s</entry>\n", - memory->memory_manufacturer); - } - if (memory->memory_serial_number != NULL) { - virBufferAdd(buf, prefix, len); - virBufferEscapeString(buf, - " <entry name='serial_number'>%s</entry>\n", - memory->memory_serial_number); - } - if (memory->memory_part_number != NULL) { - virBufferAdd(buf, prefix, len); - virBufferEscapeString(buf, - " <entry name='part_number'>%s</entry>\n", - memory->memory_part_number); - } - virBufferAsprintf(buf, "%s </memory_device>\n", prefix); - } + if (!memory->memory_size && + !memory->memory_form_factor && + !memory->memory_locator && + !memory->memory_bank_locator && + !memory->memory_type && + !memory->memory_type_detail && + !memory->memory_speed && + !memory->memory_manufacturer && + !memory->memory_serial_number && + !memory->memory_part_number) + continue; + + virBufferAddLit(buf, " <memory_device>\n"); + virBufferEscapeString(buf, " <entry name='size'>%s</entry>\n", + memory->memory_size); + virBufferEscapeString(buf, + " <entry name='form_factor'>%s</entry>\n", + memory->memory_form_factor); + virBufferEscapeString(buf, " <entry name='locator'>%s</entry>\n", + memory->memory_locator); + virBufferEscapeString(buf, + " <entry name='bank_locator'>%s</entry>\n", + memory->memory_bank_locator); + virBufferEscapeString(buf, " <entry name='type'>%s</entry>\n", + memory->memory_type); + virBufferEscapeString(buf, + " <entry name='type_detail'>%s</entry>\n", + memory->memory_type_detail); + virBufferEscapeString(buf, " <entry name='speed'>%s</entry>\n", + memory->memory_speed); + virBufferEscapeString(buf, + " <entry name='manufacturer'>%s</entry>\n", + memory->memory_manufacturer); + virBufferEscapeString(buf, + " <entry name='serial_number'>%s</entry>\n", + memory->memory_serial_number); + virBufferEscapeString(buf, + " <entry name='part_number'>%s</entry>\n", + memory->memory_part_number); + virBufferAddLit(buf, " </memory_device>\n"); } - - return; } /** * virSysinfoFormat: + * @buf: buffer to append output to (may use auto-indentation) * @def: structure to convert to xml string - * @prefix: string to prefix before each line of xml * - * This returns the XML description of the sysinfo, or NULL after - * generating an error message. + * Returns 0 on success, -1 on failure after generating an error message. */ -char * -virSysinfoFormat(virSysinfoDefPtr def, const char *prefix) +int +virSysinfoFormat(virBufferPtr buf, virSysinfoDefPtr def) { const char *type = virSysinfoTypeToString(def->type); - virBuffer buf = VIR_BUFFER_INITIALIZER; if (!type) { virSmbiosReportError(VIR_ERR_INTERNAL_ERROR, _("unexpected sysinfo type model %d"), def->type); - return NULL; + virBufferFreeAndReset(buf); + return -1; } - virBufferAsprintf(&buf, "%s<sysinfo type='%s'>\n", prefix, type); + virBufferAsprintf(buf, "<sysinfo type='%s'>\n", type); - virSysinfoBIOSFormat(def, prefix, &buf); - virSysinfoSystemFormat(def, prefix, &buf); - virSysinfoProcessorFormat(def, prefix, &buf); - virSysinfoMemoryFormat(def, prefix, &buf); + virSysinfoBIOSFormat(buf, def); + virSysinfoSystemFormat(buf, def); + virSysinfoProcessorFormat(buf, def); + virSysinfoMemoryFormat(buf, def); - virBufferAsprintf(&buf, "%s</sysinfo>\n", prefix); + virBufferAddLit(buf, "</sysinfo>\n"); - if (virBufferError(&buf)) { + if (virBufferError(buf)) { virReportOOMError(); - return NULL; + return -1; } - return virBufferContentAndReset(&buf); + return 0; } bool virSysinfoIsEqual(virSysinfoDefPtr src, diff --git a/src/util/sysinfo.h b/src/util/sysinfo.h index 86fd20f..bee43ee 100644 --- a/src/util/sysinfo.h +++ b/src/util/sysinfo.h @@ -26,6 +26,7 @@ # include "internal.h" # include "util.h" +# include "buf.h" enum virSysinfoType { VIR_SYSINFO_SMBIOS, @@ -93,7 +94,7 @@ virSysinfoDefPtr virSysinfoRead(void); void virSysinfoDefFree(virSysinfoDefPtr def); -char *virSysinfoFormat(virSysinfoDefPtr def, const char *prefix) +int virSysinfoFormat(virBufferPtr buf, virSysinfoDefPtr def) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); bool virSysinfoIsEqual(virSysinfoDefPtr src, -- 1.7.4.4

On 09/29/2011 06:22 PM, Eric Blake wrote:
The improvements to virBuffer, along with a paradigm shift to pass the original buffer through rather than creating a second buffer, allow us to shave off quite a few lines of code.
* src/util/sysinfo.h (virSysinfoFormat): Alter signature. * src/util/sysinfo.c (virSysinfoFormat, virSysinfoBIOSFormat) (virSysinfoSystemFormat, virSysinfoProcessorFormat) (virSysinfoMemoryFormat): Change indentation parameter. * src/conf/domain_conf.c (virDomainSysinfoDefFormat): Adjust caller. * src/qemu/qemu_driver.c (qemuGetSysinfo): Likewise. --- src/conf/domain_conf.c | 12 +- src/qemu/qemu_driver.c | 9 +- src/util/sysinfo.c | 399 ++++++++++++++++-------------------------------- src/util/sysinfo.h | 3 +- 4 files changed, 147 insertions(+), 276 deletions(-)
I'd squash in the attached patch, but it's not necessary as it gets rid of non automatic indentation whitespace, but makes the code look cleaner :) ACK, virBufferEscapeString nicely simplifies the code :) Peter

On Thu, Oct 20, 2011 at 12:14:57PM +0200, Peter Krempa wrote:
On 09/29/2011 06:22 PM, Eric Blake wrote:
The improvements to virBuffer, along with a paradigm shift to pass the original buffer through rather than creating a second buffer, allow us to shave off quite a few lines of code.
* src/util/sysinfo.h (virSysinfoFormat): Alter signature. * src/util/sysinfo.c (virSysinfoFormat, virSysinfoBIOSFormat) (virSysinfoSystemFormat, virSysinfoProcessorFormat) (virSysinfoMemoryFormat): Change indentation parameter. * src/conf/domain_conf.c (virDomainSysinfoDefFormat): Adjust caller. * src/qemu/qemu_driver.c (qemuGetSysinfo): Likewise. --- src/conf/domain_conf.c | 12 +- src/qemu/qemu_driver.c | 9 +- src/util/sysinfo.c | 399 ++++++++++++++++-------------------------------- src/util/sysinfo.h | 3 +- 4 files changed, 147 insertions(+), 276 deletions(-)
I'd squash in the attached patch, but it's not necessary as it gets rid of non automatic indentation whitespace, but makes the code look cleaner :)
I'm not entirely convinced this is a good idea. This means that when looking at the code, it is no longer obvious what the nesting of XML elements is supposed to be - they are all the level. I see the value of the automatic indentation code, being to allow us to embed 1 XML document, inside another XML document. eg domain conf XML, inside QEMU state XML. I don't think we should use it to remove indentation in all our code.
diff --git a/src/util/sysinfo.c b/src/util/sysinfo.c index de3108a..53636b6 100644 --- a/src/util/sysinfo.c +++ b/src/util/sysinfo.c @@ -521,16 +521,18 @@ virSysinfoBIOSFormat(virBufferPtr buf, virSysinfoDefPtr def) !def->bios_date && !def->bios_release) return;
- virBufferAddLit(buf, " <bios>\n"); - virBufferEscapeString(buf, " <entry name='vendor'>%s</entry>\n", + virBufferAddLit(buf, "<bios>\n"); + virBufferAdjustIndent(buf, 2); + virBufferEscapeString(buf, "<entry name='vendor'>%s</entry>\n", def->bios_vendor); - virBufferEscapeString(buf, " <entry name='version'>%s</entry>\n", + virBufferEscapeString(buf, "<entry name='version'>%s</entry>\n", def->bios_version); - virBufferEscapeString(buf, " <entry name='date'>%s</entry>\n", + virBufferEscapeString(buf, "<entry name='date'>%s</entry>\n", def->bios_date); - virBufferEscapeString(buf, " <entry name='release'>%s</entry>\n", + virBufferEscapeString(buf, "<entry name='release'>%s</entry>\n", def->bios_release); - virBufferAddLit(buf, " </bios>\n"); + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "</bios>\n"); }
static void @@ -541,22 +543,24 @@ virSysinfoSystemFormat(virBufferPtr buf, virSysinfoDefPtr def) !def->system_uuid && !def->system_sku && !def->system_family) return;
- virBufferAddLit(buf, " <system>\n"); - virBufferEscapeString(buf, " <entry name='manufacturer'>%s</entry>\n", + virBufferAddLit(buf, "<system>\n"); + virBufferAdjustIndent(buf, 2); + virBufferEscapeString(buf, "<entry name='manufacturer'>%s</entry>\n", def->system_manufacturer); - virBufferEscapeString(buf, " <entry name='product'>%s</entry>\n", + virBufferEscapeString(buf, "<entry name='product'>%s</entry>\n", def->system_product); - virBufferEscapeString(buf, " <entry name='version'>%s</entry>\n", + virBufferEscapeString(buf, "<entry name='version'>%s</entry>\n", def->system_version); - virBufferEscapeString(buf, " <entry name='serial'>%s</entry>\n", + virBufferEscapeString(buf, "<entry name='serial'>%s</entry>\n", def->system_serial); - virBufferEscapeString(buf, " <entry name='uuid'>%s</entry>\n", + virBufferEscapeString(buf, "<entry name='uuid'>%s</entry>\n", def->system_uuid); - virBufferEscapeString(buf, " <entry name='sku'>%s</entry>\n", + virBufferEscapeString(buf, "<entry name='sku'>%s</entry>\n", def->system_sku); - virBufferEscapeString(buf, " <entry name='family'>%s</entry>\n", + virBufferEscapeString(buf, "<entry name='family'>%s</entry>\n", def->system_family); - virBufferAddLit(buf, " </system>\n"); + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "</system>\n"); }
static void @@ -581,8 +585,8 @@ virSysinfoProcessorFormat(virBufferPtr buf, virSysinfoDefPtr def) !processor->processor_part_number) continue;
- virBufferAddLit(buf, " <processor>\n"); - virBufferAdjustIndent(buf, 4); + virBufferAddLit(buf, "<processor>\n"); + virBufferAdjustIndent(buf, 2); virBufferEscapeString(buf, "<entry name='socket_destination'>%s</entry>\n", processor->processor_socket_destination); @@ -606,8 +610,8 @@ virSysinfoProcessorFormat(virBufferPtr buf, virSysinfoDefPtr def) processor->processor_serial_number); virBufferEscapeString(buf, "<entry name='part_number'>%s</entry>\n", processor->processor_part_number); - virBufferAdjustIndent(buf, -4); - virBufferAddLit(buf, " </processor>\n"); + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "</processor>\n"); } }
@@ -632,34 +636,30 @@ virSysinfoMemoryFormat(virBufferPtr buf, virSysinfoDefPtr def) !memory->memory_part_number) continue;
- virBufferAddLit(buf, " <memory_device>\n"); - virBufferEscapeString(buf, " <entry name='size'>%s</entry>\n", + virBufferAddLit(buf, "<memory_device>\n"); + virBufferAdjustIndent(buf, 2); + virBufferEscapeString(buf, "<entry name='size'>%s</entry>\n", memory->memory_size); - virBufferEscapeString(buf, - " <entry name='form_factor'>%s</entry>\n", + virBufferEscapeString(buf, "<entry name='form_factor'>%s</entry>\n", memory->memory_form_factor); - virBufferEscapeString(buf, " <entry name='locator'>%s</entry>\n", + virBufferEscapeString(buf, "<entry name='locator'>%s</entry>\n", memory->memory_locator); - virBufferEscapeString(buf, - " <entry name='bank_locator'>%s</entry>\n", + virBufferEscapeString(buf, "<entry name='bank_locator'>%s</entry>\n", memory->memory_bank_locator); - virBufferEscapeString(buf, " <entry name='type'>%s</entry>\n", + virBufferEscapeString(buf, "<entry name='type'>%s</entry>\n", memory->memory_type); - virBufferEscapeString(buf, - " <entry name='type_detail'>%s</entry>\n", + virBufferEscapeString(buf, "<entry name='type_detail'>%s</entry>\n", memory->memory_type_detail); - virBufferEscapeString(buf, " <entry name='speed'>%s</entry>\n", + virBufferEscapeString(buf, "<entry name='speed'>%s</entry>\n", memory->memory_speed); - virBufferEscapeString(buf, - " <entry name='manufacturer'>%s</entry>\n", + virBufferEscapeString(buf, "<entry name='manufacturer'>%s</entry>\n", memory->memory_manufacturer); - virBufferEscapeString(buf, - " <entry name='serial_number'>%s</entry>\n", + virBufferEscapeString(buf, "<entry name='serial_number'>%s</entry>\n", memory->memory_serial_number); - virBufferEscapeString(buf, - " <entry name='part_number'>%s</entry>\n", + virBufferEscapeString(buf, "<entry name='part_number'>%s</entry>\n", memory->memory_part_number); - virBufferAddLit(buf, " </memory_device>\n"); + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "</memory_device>\n"); } }
@@ -684,12 +684,14 @@ virSysinfoFormat(virBufferPtr buf, virSysinfoDefPtr def) }
virBufferAsprintf(buf, "<sysinfo type='%s'>\n", type); + virBufferAdjustIndent(buf, 2);
virSysinfoBIOSFormat(buf, def); virSysinfoSystemFormat(buf, def); virSysinfoProcessorFormat(buf, def); virSysinfoMemoryFormat(buf, def);
+ virBufferAdjustIndent(buf, -2); virBufferAddLit(buf, "</sysinfo>\n");
if (virBufferError(buf)) {
Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

On 10/20/2011 12:20 PM, Daniel P. Berrange wrote:
On Thu, Oct 20, 2011 at 12:14:57PM +0200, Peter Krempa wrote:
On 09/29/2011 06:22 PM, Eric Blake wrote:
The improvements to virBuffer, along with a paradigm shift to pass the original buffer through rather than creating a second buffer, allow us to shave off quite a few lines of code.
* src/util/sysinfo.h (virSysinfoFormat): Alter signature. * src/util/sysinfo.c (virSysinfoFormat, virSysinfoBIOSFormat) (virSysinfoSystemFormat, virSysinfoProcessorFormat) (virSysinfoMemoryFormat): Change indentation parameter. * src/conf/domain_conf.c (virDomainSysinfoDefFormat): Adjust caller. * src/qemu/qemu_driver.c (qemuGetSysinfo): Likewise. --- src/conf/domain_conf.c | 12 +- src/qemu/qemu_driver.c | 9 +- src/util/sysinfo.c | 399 ++++++++++++++++-------------------------------- src/util/sysinfo.h | 3 +- 4 files changed, 147 insertions(+), 276 deletions(-)
I'd squash in the attached patch, but it's not necessary as it gets rid of non automatic indentation whitespace, but makes the code look cleaner :)
I'm not entirely convinced this is a good idea. This means that when looking at the code, it is no longer obvious what the nesting of XML elements is supposed to be - they are all the level.
I see the value of the automatic indentation code, being to allow us to embed 1 XML document, inside another XML document. eg domain conf XML, inside QEMU state XML.
I don't think we should use it to remove indentation in all our code.
Oh well, maybe I got too far with removing indentation, but I think that functions outputing XML should have a consistent default indentation (0 or 2 spaces), so when embedding them in more complex XML documents as sub-elemets, we will not have to check wether this function is at col 0 relative from the caller or on column 2. I agree that it's not necessary to change everything, but it'd be nice to have a consistent way to do this. Peter

On Thu, Oct 20, 2011 at 03:03:25PM +0200, Peter Krempa wrote:
On 10/20/2011 12:20 PM, Daniel P. Berrange wrote:
On Thu, Oct 20, 2011 at 12:14:57PM +0200, Peter Krempa wrote:
On 09/29/2011 06:22 PM, Eric Blake wrote:
The improvements to virBuffer, along with a paradigm shift to pass the original buffer through rather than creating a second buffer, allow us to shave off quite a few lines of code.
* src/util/sysinfo.h (virSysinfoFormat): Alter signature. * src/util/sysinfo.c (virSysinfoFormat, virSysinfoBIOSFormat) (virSysinfoSystemFormat, virSysinfoProcessorFormat) (virSysinfoMemoryFormat): Change indentation parameter. * src/conf/domain_conf.c (virDomainSysinfoDefFormat): Adjust caller. * src/qemu/qemu_driver.c (qemuGetSysinfo): Likewise. --- src/conf/domain_conf.c | 12 +- src/qemu/qemu_driver.c | 9 +- src/util/sysinfo.c | 399 ++++++++++++++++-------------------------------- src/util/sysinfo.h | 3 +- 4 files changed, 147 insertions(+), 276 deletions(-)
I'd squash in the attached patch, but it's not necessary as it gets rid of non automatic indentation whitespace, but makes the code look cleaner :)
I'm not entirely convinced this is a good idea. This means that when looking at the code, it is no longer obvious what the nesting of XML elements is supposed to be - they are all the level.
I see the value of the automatic indentation code, being to allow us to embed 1 XML document, inside another XML document. eg domain conf XML, inside QEMU state XML.
I don't think we should use it to remove indentation in all our code.
Oh well, maybe I got too far with removing indentation, but I think that functions outputing XML should have a consistent default indentation (0 or 2 spaces), so when embedding them in more complex XML documents as sub-elemets, we will not have to check wether this function is at col 0 relative from the caller or on column 2. I agree that it's not necessary to change everything, but it'd be nice to have a consistent way to do this.
The only sane option is for any function generating an embeddable XML document to default to zero top level indent. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

On 10/20/2011 04:20 AM, Daniel P. Berrange wrote:
On Thu, Oct 20, 2011 at 12:14:57PM +0200, Peter Krempa wrote:
On 09/29/2011 06:22 PM, Eric Blake wrote:
The improvements to virBuffer, along with a paradigm shift to pass the original buffer through rather than creating a second buffer, allow us to shave off quite a few lines of code.
I'd squash in the attached patch, but it's not necessary as it gets rid of non automatic indentation whitespace, but makes the code look cleaner :)
I'm not entirely convinced this is a good idea. This means that when looking at the code, it is no longer obvious what the nesting of XML elements is supposed to be - they are all the level.
I concur with Daniel here - I debated about dropping the leading whitespace and using a lot more virBufferAdjustIndent when first writing this series (since it would have been less work to convert from my v1, where I had already removed all the leading whitespace anyways), but it just doesn't scale as well. My end decision was to only remove whitespace and start at level 0 just for the functions that can be called from multiple locations; single-use call-chains were easier to keep indented as they were before the series. The only reason I used virBufferAdjustIndent inside virSysinfoProcessorFormat, against the rule of thumb that I generally used of keeping the in-function indentation, was to fit things in 80 columns.
ACK, virBufferEscapeString nicely simplifies the code :)
Pushed. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On 10/21/2011 06:41 AM, Eric Blake wrote:
On 10/20/2011 04:20 AM, Daniel P. Berrange wrote:
On Thu, Oct 20, 2011 at 12:14:57PM +0200, Peter Krempa wrote:
On 09/29/2011 06:22 PM, Eric Blake wrote:
The improvements to virBuffer, along with a paradigm shift to pass the original buffer through rather than creating a second buffer, allow us to shave off quite a few lines of code.
I'd squash in the attached patch, but it's not necessary as it gets rid of non automatic indentation whitespace, but makes the code look cleaner :)
I'm not entirely convinced this is a good idea. This means that when looking at the code, it is no longer obvious what the nesting of XML elements is supposed to be - they are all the level.
I concur with Daniel here - I debated about dropping the leading whitespace and using a lot more virBufferAdjustIndent when first writing this series (since it would have been less work to convert from my v1, where I had already removed all the leading whitespace anyways), but it just doesn't scale as well. My end decision was to only remove whitespace and start at level 0 just for the functions that can be called from multiple locations; single-use call-chains were easier to keep indented as they were before the series.
The only reason I used virBufferAdjustIndent inside virSysinfoProcessorFormat, against the rule of thumb that I generally used of keeping the in-function indentation, was to fit things in 80 columns.
I agree with you and that's a reasonable reason.:-)
ACK, virBufferEscapeString nicely simplifies the code :)
Pushed.

Auto-indent makes life a bit easier; this patch also drops unused arguments and fixes a flag name. * src/conf/cpu_conf.h (virCPUFormatFlags): Fix typo. (virCPUDefFormat, virCPUDefFormatBuf): Drop unused arguments. * src/conf/cpu_conf.c (virCPUDefFormat, virCPUDefFormatBuf): Simplify indentation. * src/conf/domain_conf.c (virDomainDefFormatInternal): Adjust caller. * src/conf/capabilities.c (virCapabilitiesFormatXML): Likewise. * src/cpu/cpu.c (cpuBaselineXML): Likewise. * tests/cputest.c (cpuTestCompareXML): Likewise. --- src/conf/capabilities.c | 8 +++++--- src/conf/cpu_conf.c | 42 +++++++++++++++++------------------------- src/conf/cpu_conf.h | 9 +++------ src/conf/domain_conf.c | 4 +++- src/cpu/cpu.c | 2 +- tests/cputest.c | 2 +- 6 files changed, 30 insertions(+), 37 deletions(-) diff --git a/src/conf/capabilities.c b/src/conf/capabilities.c index 2f243ae..5f7f768 100644 --- a/src/conf/capabilities.c +++ b/src/conf/capabilities.c @@ -1,7 +1,7 @@ /* * capabilities.c: hypervisor capabilities * - * Copyright (C) 2006-2008, 2010 Red Hat, Inc. + * Copyright (C) 2006-2008, 2010-2011 Red Hat, Inc. * Copyright (C) 2006-2008 Daniel P. Berrange * * This library is free software; you can redistribute it and/or @@ -681,8 +681,10 @@ virCapabilitiesFormatXML(virCapsPtr caps) virBufferAddLit(&xml, " </features>\n"); } - virCPUDefFormatBuf(&xml, caps->host.cpu, " ", - VIR_CPU_FORMAT_EMBEDED); + /* virCPUDefFormatBuf with EMBEDDED uses indent of 2, we want 4 more */ + virBufferAdjustIndent(&xml, 4); + virCPUDefFormatBuf(&xml, caps->host.cpu, VIR_CPU_FORMAT_EMBEDDED); + virBufferAdjustIndent(&xml, -4); virBufferAddLit(&xml, " </cpu>\n"); diff --git a/src/conf/cpu_conf.c b/src/conf/cpu_conf.c index 5cecda2..49ea392 100644 --- a/src/conf/cpu_conf.c +++ b/src/conf/cpu_conf.c @@ -305,13 +305,11 @@ error: char * -virCPUDefFormat(virCPUDefPtr def, - const char *indent, - unsigned int flags) +virCPUDefFormat(virCPUDefPtr def) { virBuffer buf = VIR_BUFFER_INITIALIZER; - if (virCPUDefFormatBuf(&buf, def, indent, flags) < 0) + if (virCPUDefFormatBuf(&buf, def, 0) < 0) goto cleanup; if (virBufferError(&buf)) @@ -330,7 +328,6 @@ cleanup: int virCPUDefFormatBuf(virBufferPtr buf, virCPUDefPtr def, - const char *indent, unsigned int flags) { unsigned int i; @@ -338,16 +335,13 @@ virCPUDefFormatBuf(virBufferPtr buf, if (!def) return 0; - if (indent == NULL) - indent = ""; - if (!def->model && def->nfeatures) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Non-empty feature list specified without CPU model")); return -1; } - if (!(flags & VIR_CPU_FORMAT_EMBEDED)) { + if (!(flags & VIR_CPU_FORMAT_EMBEDDED)) { if (def->type == VIR_CPU_TYPE_GUEST && def->model) { const char *match; if (!(match = virCPUMatchTypeToString(def->match))) { @@ -356,25 +350,24 @@ virCPUDefFormatBuf(virBufferPtr buf, return -1; } - virBufferAsprintf(buf, "%s<cpu match='%s'>\n", indent, match); + virBufferAsprintf(buf, "<cpu match='%s'>\n", match); + } else { + virBufferAddLit(buf, "<cpu>\n"); } - else - virBufferAsprintf(buf, "%s<cpu>\n", indent); if (def->arch) - virBufferAsprintf(buf, "%s <arch>%s</arch>\n", indent, def->arch); + virBufferAsprintf(buf, " <arch>%s</arch>\n", def->arch); } if (def->model) - virBufferAsprintf(buf, "%s <model>%s</model>\n", indent, def->model); + virBufferAsprintf(buf, " <model>%s</model>\n", def->model); if (def->vendor) { - virBufferAsprintf(buf, "%s <vendor>%s</vendor>\n", - indent, def->vendor); + virBufferAsprintf(buf, " <vendor>%s</vendor>\n", def->vendor); } if (def->sockets && def->cores && def->threads) { - virBufferAsprintf(buf, "%s <topology", indent); + virBufferAddLit(buf, " <topology"); virBufferAsprintf(buf, " sockets='%u'", def->sockets); virBufferAsprintf(buf, " cores='%u'", def->cores); virBufferAsprintf(buf, " threads='%u'", def->threads); @@ -399,17 +392,16 @@ virCPUDefFormatBuf(virBufferPtr buf, _("Unexpected CPU feature policy %d"), feature->policy); return -1; } - virBufferAsprintf(buf, "%s <feature policy='%s' name='%s'/>\n", - indent, policy, feature->name); - } - else { - virBufferAsprintf(buf, "%s <feature name='%s'/>\n", - indent, feature->name); + virBufferAsprintf(buf, " <feature policy='%s' name='%s'/>\n", + policy, feature->name); + } else { + virBufferAsprintf(buf, " <feature name='%s'/>\n", + feature->name); } } - if (!(flags & VIR_CPU_FORMAT_EMBEDED)) - virBufferAsprintf(buf, "%s</cpu>\n", indent); + if (!(flags & VIR_CPU_FORMAT_EMBEDDED)) + virBufferAddLit(buf, "</cpu>\n"); return 0; } diff --git a/src/conf/cpu_conf.h b/src/conf/cpu_conf.h index 57b85e1..409bbca 100644 --- a/src/conf/cpu_conf.h +++ b/src/conf/cpu_conf.h @@ -96,8 +96,8 @@ virCPUDefParseXML(const xmlNodePtr node, enum virCPUType mode); enum virCPUFormatFlags { - VIR_CPU_FORMAT_EMBEDED = (1 << 0) /* embed into existing <cpu/> element - * in host capabilities */ + VIR_CPU_FORMAT_EMBEDDED = (1 << 0) /* embed into existing <cpu/> element + * in host capabilities */ }; bool @@ -105,14 +105,11 @@ virCPUDefIsEqual(virCPUDefPtr src, virCPUDefPtr dst); char * -virCPUDefFormat(virCPUDefPtr def, - const char *indent, - unsigned int flags); +virCPUDefFormat(virCPUDefPtr def); int virCPUDefFormatBuf(virBufferPtr buf, virCPUDefPtr def, - const char *indent, unsigned int flags); int diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index eb82fa6..40b06f3 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -10749,8 +10749,10 @@ virDomainDefFormatInternal(virDomainDefPtr def, virBufferAddLit(buf, " </features>\n"); } - if (virCPUDefFormatBuf(buf, def->cpu, " ", 0) < 0) + virBufferAdjustIndent(buf, 2); + if (virCPUDefFormatBuf(buf, def->cpu, 0) < 0) goto cleanup; + virBufferAdjustIndent(buf, -2); virBufferAsprintf(buf, " <clock offset='%s'", virDomainClockOffsetTypeToString(def->clock.offset)); diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 2906be9..b919b6e 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -320,7 +320,7 @@ cpuBaselineXML(const char **xmlCPUs, if (!(cpu = cpuBaseline(cpus, ncpus, models, nmodels))) goto error; - cpustr = virCPUDefFormat(cpu, "", 0); + cpustr = virCPUDefFormat(cpu); cleanup: if (cpus) { diff --git a/tests/cputest.c b/tests/cputest.c index b5272c1..36b3eb4 100644 --- a/tests/cputest.c +++ b/tests/cputest.c @@ -176,7 +176,7 @@ cpuTestCompareXML(const char *arch, if (virtTestLoadFile(xml, &expected) < 0) goto cleanup; - if (!(actual = virCPUDefFormat(cpu, NULL, 0))) + if (!(actual = virCPUDefFormat(cpu))) goto cleanup; if (STRNEQ(expected, actual)) { -- 1.7.4.4

On 09/29/2011 06:22 PM, Eric Blake wrote:
Auto-indent makes life a bit easier; this patch also drops unused arguments and fixes a flag name.
* src/conf/cpu_conf.h (virCPUFormatFlags): Fix typo. (virCPUDefFormat, virCPUDefFormatBuf): Drop unused arguments. * src/conf/cpu_conf.c (virCPUDefFormat, virCPUDefFormatBuf): Simplify indentation. * src/conf/domain_conf.c (virDomainDefFormatInternal): Adjust caller. * src/conf/capabilities.c (virCapabilitiesFormatXML): Likewise. * src/cpu/cpu.c (cpuBaselineXML): Likewise. * tests/cputest.c (cpuTestCompareXML): Likewise. --- src/conf/capabilities.c | 8 +++++--- src/conf/cpu_conf.c | 42 +++++++++++++++++------------------------- src/conf/cpu_conf.h | 9 +++------ src/conf/domain_conf.c | 4 +++- src/cpu/cpu.c | 2 +- tests/cputest.c | 2 +- 6 files changed, 30 insertions(+), 37 deletions(-)
diff --git a/src/conf/capabilities.c b/src/conf/capabilities.c index 2f243ae..5f7f768 100644 --- a/src/conf/capabilities.c +++ b/src/conf/capabilities.c
@@ -681,8 +681,10 @@ virCapabilitiesFormatXML(virCapsPtr caps) virBufferAddLit(&xml, "</features>\n"); }
- virCPUDefFormatBuf(&xml, caps->host.cpu, " ", - VIR_CPU_FORMAT_EMBEDED); + /* virCPUDefFormatBuf with EMBEDDED uses indent of 2, we want 4 more */ + virBufferAdjustIndent(&xml, 4); + virCPUDefFormatBuf(&xml, caps->host.cpu, VIR_CPU_FORMAT_EMBEDDED); + virBufferAdjustIndent(&xml, -4);
Oh well. I don't like this very much, but removing things like this would ultimately end in having a flat XML output structure and using indentation adjustment to have correct indentation across the xml, which is somewhat controversial. Well, it doesn't affect functionality, so it's not a show-stoping issue.
virBufferAddLit(&xml, "</cpu>\n");
Otherwise, this patch works correct, so ACK. Peter

On 10/20/2011 06:35 AM, Peter Krempa wrote:
On 09/29/2011 06:22 PM, Eric Blake wrote:
Auto-indent makes life a bit easier; this patch also drops unused arguments and fixes a flag name.
* src/conf/cpu_conf.h (virCPUFormatFlags): Fix typo. (virCPUDefFormat, virCPUDefFormatBuf): Drop unused arguments. * src/conf/cpu_conf.c (virCPUDefFormat, virCPUDefFormatBuf): Simplify indentation. * src/conf/domain_conf.c (virDomainDefFormatInternal): Adjust caller. * src/conf/capabilities.c (virCapabilitiesFormatXML): Likewise. * src/cpu/cpu.c (cpuBaselineXML): Likewise. * tests/cputest.c (cpuTestCompareXML): Likewise. --- src/conf/capabilities.c | 8 +++++--- src/conf/cpu_conf.c | 42 +++++++++++++++++------------------------- src/conf/cpu_conf.h | 9 +++------ src/conf/domain_conf.c | 4 +++- src/cpu/cpu.c | 2 +- tests/cputest.c | 2 +- 6 files changed, 30 insertions(+), 37 deletions(-)
diff --git a/src/conf/capabilities.c b/src/conf/capabilities.c index 2f243ae..5f7f768 100644 --- a/src/conf/capabilities.c +++ b/src/conf/capabilities.c
@@ -681,8 +681,10 @@ virCapabilitiesFormatXML(virCapsPtr caps) virBufferAddLit(&xml, "</features>\n"); }
- virCPUDefFormatBuf(&xml, caps->host.cpu, " ", - VIR_CPU_FORMAT_EMBEDED); + /* virCPUDefFormatBuf with EMBEDDED uses indent of 2, we want 4 more */ + virBufferAdjustIndent(&xml, 4); + virCPUDefFormatBuf(&xml, caps->host.cpu, VIR_CPU_FORMAT_EMBEDDED); + virBufferAdjustIndent(&xml, -4);
Oh well. I don't like this very much, but removing things like this would ultimately end in having a flat XML output structure and using indentation adjustment to have correct indentation across the xml, which is somewhat controversial. Well, it doesn't affect functionality, so it's not a show-stoping issue.
I don't like how VIR_CPU_FORMAT_EMBED[D]ED was used either. So on review, I think it's better to split this one into multiple functions, specifically catering to each caller, with each embeddable call-point starting at 0 indentation.
Otherwise, this patch works correct, so ACK.
I went ahead and squashed this in before pushing. diff --git i/src/conf/capabilities.c w/src/conf/capabilities.c index 5f7f768..40e2976 100644 --- i/src/conf/capabilities.c +++ w/src/conf/capabilities.c @@ -681,10 +681,9 @@ virCapabilitiesFormatXML(virCapsPtr caps) virBufferAddLit(&xml, " </features>\n"); } - /* virCPUDefFormatBuf with EMBEDDED uses indent of 2, we want 4 more */ - virBufferAdjustIndent(&xml, 4); - virCPUDefFormatBuf(&xml, caps->host.cpu, VIR_CPU_FORMAT_EMBEDDED); - virBufferAdjustIndent(&xml, -4); + virBufferAdjustIndent(&xml, 6); + virCPUDefFormatBuf(&xml, caps->host.cpu); + virBufferAdjustIndent(&xml, -6); virBufferAddLit(&xml, " </cpu>\n"); diff --git i/src/conf/cpu_conf.c w/src/conf/cpu_conf.c index 49ea392..41e997e 100644 --- i/src/conf/cpu_conf.c +++ w/src/conf/cpu_conf.c @@ -309,7 +309,7 @@ virCPUDefFormat(virCPUDefPtr def) { virBuffer buf = VIR_BUFFER_INITIALIZER; - if (virCPUDefFormatBuf(&buf, def, 0) < 0) + if (virCPUDefFormatBufFull(&buf, def) < 0) goto cleanup; if (virBufferError(&buf)) @@ -326,9 +326,41 @@ cleanup: int +virCPUDefFormatBufFull(virBufferPtr buf, + virCPUDefPtr def) +{ + if (!def) + return 0; + + if (def->type == VIR_CPU_TYPE_GUEST && def->model) { + const char *match; + if (!(match = virCPUMatchTypeToString(def->match))) { + virCPUReportError(VIR_ERR_INTERNAL_ERROR, + _("Unexpected CPU match policy %d"), def->match); + return -1; + } + + virBufferAsprintf(buf, "<cpu match='%s'>\n", match); + } else { + virBufferAddLit(buf, "<cpu>\n"); + } + + if (def->arch) + virBufferAsprintf(buf, " <arch>%s</arch>\n", def->arch); + + virBufferAdjustIndent(buf, 2); + if (virCPUDefFormatBuf(buf, def) < 0) + return -1; + virBufferAdjustIndent(buf, -2); + + virBufferAddLit(buf, "</cpu>\n"); + + return 0; +} + +int virCPUDefFormatBuf(virBufferPtr buf, - virCPUDefPtr def, - unsigned int flags) + virCPUDefPtr def) { unsigned int i; @@ -341,33 +373,15 @@ virCPUDefFormatBuf(virBufferPtr buf, return -1; } - if (!(flags & VIR_CPU_FORMAT_EMBEDDED)) { - if (def->type == VIR_CPU_TYPE_GUEST && def->model) { - const char *match; - if (!(match = virCPUMatchTypeToString(def->match))) { - virCPUReportError(VIR_ERR_INTERNAL_ERROR, - _("Unexpected CPU match policy %d"), def->match); - return -1; - } - - virBufferAsprintf(buf, "<cpu match='%s'>\n", match); - } else { - virBufferAddLit(buf, "<cpu>\n"); - } - - if (def->arch) - virBufferAsprintf(buf, " <arch>%s</arch>\n", def->arch); - } - if (def->model) - virBufferAsprintf(buf, " <model>%s</model>\n", def->model); + virBufferAsprintf(buf, "<model>%s</model>\n", def->model); if (def->vendor) { - virBufferAsprintf(buf, " <vendor>%s</vendor>\n", def->vendor); + virBufferAsprintf(buf, "<vendor>%s</vendor>\n", def->vendor); } if (def->sockets && def->cores && def->threads) { - virBufferAddLit(buf, " <topology"); + virBufferAddLit(buf, "<topology"); virBufferAsprintf(buf, " sockets='%u'", def->sockets); virBufferAsprintf(buf, " cores='%u'", def->cores); virBufferAsprintf(buf, " threads='%u'", def->threads); @@ -392,17 +406,14 @@ virCPUDefFormatBuf(virBufferPtr buf, _("Unexpected CPU feature policy %d"), feature->policy); return -1; } - virBufferAsprintf(buf, " <feature policy='%s' name='%s'/>\n", + virBufferAsprintf(buf, "<feature policy='%s' name='%s'/>\n", policy, feature->name); } else { - virBufferAsprintf(buf, " <feature name='%s'/>\n", + virBufferAsprintf(buf, "<feature name='%s'/>\n", feature->name); } } - if (!(flags & VIR_CPU_FORMAT_EMBEDDED)) - virBufferAddLit(buf, "</cpu>\n"); - return 0; } diff --git i/src/conf/cpu_conf.h w/src/conf/cpu_conf.h index 409bbca..4406cba 100644 --- i/src/conf/cpu_conf.h +++ w/src/conf/cpu_conf.h @@ -95,11 +95,6 @@ virCPUDefParseXML(const xmlNodePtr node, xmlXPathContextPtr ctxt, enum virCPUType mode); -enum virCPUFormatFlags { - VIR_CPU_FORMAT_EMBEDDED = (1 << 0) /* embed into existing <cpu/> element - * in host capabilities */ -}; - bool virCPUDefIsEqual(virCPUDefPtr src, virCPUDefPtr dst); @@ -109,8 +104,10 @@ virCPUDefFormat(virCPUDefPtr def); int virCPUDefFormatBuf(virBufferPtr buf, - virCPUDefPtr def, - unsigned int flags); + virCPUDefPtr def); +int +virCPUDefFormatBufFull(virBufferPtr buf, + virCPUDefPtr def); int virCPUDefAddFeature(virCPUDefPtr cpu, diff --git i/src/conf/domain_conf.c w/src/conf/domain_conf.c index 314e4fc..304d1a8 100644 --- i/src/conf/domain_conf.c +++ w/src/conf/domain_conf.c @@ -10826,7 +10826,7 @@ virDomainDefFormatInternal(virDomainDefPtr def, } virBufferAdjustIndent(buf, 2); - if (virCPUDefFormatBuf(buf, def->cpu, 0) < 0) + if (virCPUDefFormatBufFull(buf, def->cpu) < 0) goto cleanup; virBufferAdjustIndent(buf, -2); -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

More simplifications possible due to auto-indent. Also, <bandwidth> within <actual> was only using 6 instead of 8 spaces. * src/util/network.h (virVirtualPortProfileFormat) (virBandwidthDefFormat): Alter signature. * src/util/network.c (virVirtualPortProfileFormat) (virBandwidthDefFormat): Alter indentation. (virBandwidthChildDefFormat): Tweak to make use easier. * src/conf/network_conf.c (virPortGroupDefFormat) (virNetworkDefFormat): Adjust callers. * src/conf/domain_conf.c (virDomainNetDefFormat): Likewise. (virDomainActualNetDefFormat): Likewise, and fix bandwidth indentation. --- src/conf/domain_conf.c | 23 ++++++++++++++------- src/conf/network_conf.c | 14 +++++++++--- src/util/network.c | 49 ++++++++++++++++------------------------------ src/util/network.h | 11 ++++----- 4 files changed, 47 insertions(+), 50 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 40b06f3..70201af 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -9415,15 +9415,18 @@ virDomainActualNetDefFormat(virBufferPtr buf, return ret; } virBufferAsprintf(buf, " mode='%s'/>\n", mode); - virVirtualPortProfileFormat(buf, def->data.direct.virtPortProfile, - " "); + virBufferAdjustIndent(buf, 8); + virVirtualPortProfileFormat(buf, def->data.direct.virtPortProfile); + virBufferAdjustIndent(buf, -8); break; default: break; } - if (virBandwidthDefFormat(buf, def->bandwidth, " ") < 0) + virBufferAdjustIndent(buf, 8); + if (virBandwidthDefFormat(buf, def->bandwidth) < 0) goto error; + virBufferAdjustIndent(buf, -8); virBufferAddLit(buf, " </actual>\n"); @@ -9462,8 +9465,9 @@ virDomainNetDefFormat(virBufferPtr buf, def->data.network.portgroup); } virBufferAddLit(buf, "/>\n"); - virVirtualPortProfileFormat(buf, def->data.network.virtPortProfile, - " "); + virBufferAdjustIndent(buf, 6); + virVirtualPortProfileFormat(buf, def->data.network.virtPortProfile); + virBufferAdjustIndent(buf, -6); if ((flags & VIR_DOMAIN_XML_INTERNAL_ACTUAL_NET) && (virDomainActualNetDefFormat(buf, def->data.network.actual) < 0)) return -1; @@ -9514,8 +9518,9 @@ virDomainNetDefFormat(virBufferPtr buf, virBufferAsprintf(buf, " mode='%s'", virMacvtapModeTypeToString(def->data.direct.mode)); virBufferAddLit(buf, "/>\n"); - virVirtualPortProfileFormat(buf, def->data.direct.virtPortProfile, - " "); + virBufferAdjustIndent(buf, 6); + virVirtualPortProfileFormat(buf, def->data.direct.virtPortProfile); + virBufferAdjustIndent(buf, -6); break; case VIR_DOMAIN_NET_TYPE_USER: @@ -9580,8 +9585,10 @@ virDomainNetDefFormat(virBufferPtr buf, virBufferAsprintf(buf, " <link state='%s'/>\n", virDomainNetInterfaceLinkStateTypeToString(def->linkstate)); - if (virBandwidthDefFormat(buf, def->bandwidth, " ") < 0) + virBufferAdjustIndent(buf, 6); + if (virBandwidthDefFormat(buf, def->bandwidth) < 0) return -1; + virBufferAdjustIndent(buf, -6); if (virDomainDeviceInfoFormat(buf, &def->info, flags) < 0) return -1; diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c index b98ffad..7bc2e2c 100644 --- a/src/conf/network_conf.c +++ b/src/conf/network_conf.c @@ -1267,8 +1267,10 @@ virPortGroupDefFormat(virBufferPtr buf, virBufferAddLit(buf, " default='yes'"); } virBufferAddLit(buf, ">\n"); - virVirtualPortProfileFormat(buf, def->virtPortProfile, " "); - virBandwidthDefFormat(buf, def->bandwidth, " "); + virBufferAdjustIndent(buf, 4); + virVirtualPortProfileFormat(buf, def->virtPortProfile); + virBandwidthDefFormat(buf, def->bandwidth); + virBufferAdjustIndent(buf, -4); virBufferAddLit(buf, " </portgroup>\n"); } @@ -1341,15 +1343,19 @@ char *virNetworkDefFormat(const virNetworkDefPtr def) if (virNetworkDNSDefFormat(&buf, def->dns) < 0) goto error; - if (virBandwidthDefFormat(&buf, def->bandwidth, " ") < 0) + virBufferAdjustIndent(&buf, 2); + if (virBandwidthDefFormat(&buf, def->bandwidth) < 0) goto error; + virBufferAdjustIndent(&buf, -2); for (ii = 0; ii < def->nips; ii++) { if (virNetworkIpDefFormat(&buf, &def->ips[ii]) < 0) goto error; } - virVirtualPortProfileFormat(&buf, def->virtPortProfile, " "); + virBufferAdjustIndent(&buf, 2); + virVirtualPortProfileFormat(&buf, def->virtPortProfile); + virBufferAdjustIndent(&buf, -2); for (ii = 0; ii < def->nPortGroups; ii++) virPortGroupDefFormat(&buf, &def->portGroups[ii]); diff --git a/src/util/network.c b/src/util/network.c index ee69557..edf9c50 100644 --- a/src/util/network.c +++ b/src/util/network.c @@ -881,16 +881,14 @@ virVirtualPortProfileEqual(virVirtualPortProfileParamsPtr a, virVirtualPortProfi void virVirtualPortProfileFormat(virBufferPtr buf, - virVirtualPortProfileParamsPtr virtPort, - const char *indent) + virVirtualPortProfileParamsPtr virtPort) { char uuidstr[VIR_UUID_STRING_BUFLEN]; if (!virtPort || virtPort->virtPortType == VIR_VIRTUALPORT_NONE) return; - virBufferAsprintf(buf, "%s<virtualport type='%s'>\n", - indent, + virBufferAsprintf(buf, "<virtualport type='%s'>\n", virVirtualPortTypeToString(virtPort->virtPortType)); switch (virtPort->virtPortType) { @@ -902,9 +900,8 @@ virVirtualPortProfileFormat(virBufferPtr buf, virUUIDFormat(virtPort->u.virtPort8021Qbg.instanceID, uuidstr); virBufferAsprintf(buf, - "%s <parameters managerid='%d' typeid='%d' " + " <parameters managerid='%d' typeid='%d' " "typeidversion='%d' instanceid='%s'/>\n", - indent, virtPort->u.virtPort8021Qbg.managerID, virtPort->u.virtPort8021Qbg.typeID, virtPort->u.virtPort8021Qbg.typeIDVersion, @@ -913,13 +910,12 @@ virVirtualPortProfileFormat(virBufferPtr buf, case VIR_VIRTUALPORT_8021QBH: virBufferAsprintf(buf, - "%s <parameters profileid='%s'/>\n", - indent, + " <parameters profileid='%s'/>\n", virtPort->u.virtPort8021Qbh.profileID); break; } - virBufferAsprintf(buf, "%s</virtualport>\n", indent); + virBufferAddLit(buf, "</virtualport>\n"); } static int @@ -1074,11 +1070,14 @@ virBandwidthChildDefFormat(virBufferPtr buf, virRatePtr def, const char *elem_name) { - if (!buf || !def || !elem_name) + if (!buf || !elem_name) return -1; + if (!def) + return 0; if (def->average) { - virBufferAsprintf(buf, "<%s average='%llu'", elem_name, def->average); + virBufferAsprintf(buf, " <%s average='%llu'", elem_name, + def->average); if (def->peak) virBufferAsprintf(buf, " peak='%llu'", def->peak); @@ -1095,17 +1094,15 @@ virBandwidthChildDefFormat(virBufferPtr buf, * virBandwidthDefFormat: * @buf: Buffer to print to * @def: Data source - * @indent: prepend all lines printed with this * * Formats bandwidth and prepend each line with @indent. - * Passing NULL to @indent is equivalent passing "". + * @buf may use auto-indentation. * * Returns 0 on success, else -1. */ int virBandwidthDefFormat(virBufferPtr buf, - virBandwidthPtr def, - const char *indent) + virBandwidthPtr def) { int ret = -1; @@ -1117,23 +1114,11 @@ virBandwidthDefFormat(virBufferPtr buf, goto cleanup; } - if (!indent) - indent = ""; - - virBufferAsprintf(buf, "%s<bandwidth>\n", indent); - if (def->in) { - virBufferAsprintf(buf, "%s ", indent); - if (virBandwidthChildDefFormat(buf, def->in, "inbound") < 0) - goto cleanup; - } - - if (def->out) { - virBufferAsprintf(buf, "%s ", indent); - if (virBandwidthChildDefFormat(buf, def->out, "outbound") < 0) - goto cleanup; - } - - virBufferAsprintf(buf, "%s</bandwidth>\n", indent); + virBufferAddLit(buf, "<bandwidth>\n"); + if (virBandwidthChildDefFormat(buf, def->in, "inbound") < 0 || + virBandwidthChildDefFormat(buf, def->out, "outbound") < 0) + goto cleanup; + virBufferAddLit(buf, "</bandwidth>\n"); ret = 0; diff --git a/src/util/network.h b/src/util/network.h index 4d195af..552d5fd 100644 --- a/src/util/network.h +++ b/src/util/network.h @@ -1,7 +1,7 @@ /* * network.h: network helper APIs for libvirt * - * Copyright (C) 2009-2009 Red Hat, Inc. + * Copyright (C) 2009-2009, 2011 Red Hat, Inc. * * See COPYING.LIB for the License of this software * @@ -147,16 +147,15 @@ virVirtualPortProfileParseXML(xmlNodePtr node, virVirtualPortProfileParamsPtr *virtPort); void virVirtualPortProfileFormat(virBufferPtr buf, - virVirtualPortProfileParamsPtr virtPort, - const char *indent); + virVirtualPortProfileParamsPtr virtPort); -bool virVirtualPortProfileEqual(virVirtualPortProfileParamsPtr a, virVirtualPortProfileParamsPtr b); +bool virVirtualPortProfileEqual(virVirtualPortProfileParamsPtr a, + virVirtualPortProfileParamsPtr b); virBandwidthPtr virBandwidthDefParseNode(xmlNodePtr node); void virBandwidthDefFree(virBandwidthPtr def); int virBandwidthDefFormat(virBufferPtr buf, - virBandwidthPtr def, - const char *indent); + virBandwidthPtr def); int virBandwidthEnable(virBandwidthPtr bandwidth, const char *iface); int virBandwidthDisable(const char *iface, bool may_fail); -- 1.7.4.4

On 09/29/2011 06:22 PM, Eric Blake wrote:
More simplifications possible due to auto-indent. Also, <bandwidth> within<actual> was only using 6 instead of 8 spaces.
* src/util/network.h (virVirtualPortProfileFormat) (virBandwidthDefFormat): Alter signature. * src/util/network.c (virVirtualPortProfileFormat) (virBandwidthDefFormat): Alter indentation. (virBandwidthChildDefFormat): Tweak to make use easier. * src/conf/network_conf.c (virPortGroupDefFormat) (virNetworkDefFormat): Adjust callers. * src/conf/domain_conf.c (virDomainNetDefFormat): Likewise. (virDomainActualNetDefFormat): Likewise, and fix bandwidth indentation. --- src/conf/domain_conf.c | 23 ++++++++++++++------- src/conf/network_conf.c | 14 +++++++++--- src/util/network.c | 49 ++++++++++++++++------------------------------ src/util/network.h | 11 ++++----- 4 files changed, 47 insertions(+), 50 deletions(-)
diff --git a/src/util/network.h b/src/util/network.h index 4d195af..552d5fd 100644 --- a/src/util/network.h +++ b/src/util/network.h @@ -1,7 +1,7 @@ /* * network.h: network helper APIs for libvirt * - * Copyright (C) 2009-2009 Red Hat, Inc. + * Copyright (C) 2009-2009, 2011 Red Hat, Inc.
2009-2009? Wouldn't it be better to state "2009, 20011"?
*
ACK, Peter

On 10/20/2011 07:00 AM, Peter Krempa wrote:
On 09/29/2011 06:22 PM, Eric Blake wrote:
More simplifications possible due to auto-indent. Also, <bandwidth> within<actual> was only using 6 instead of 8 spaces.
+++ b/src/util/network.h @@ -1,7 +1,7 @@ /* * network.h: network helper APIs for libvirt * - * Copyright (C) 2009-2009 Red Hat, Inc. + * Copyright (C) 2009-2009, 2011 Red Hat, Inc.
2009-2009? Wouldn't it be better to state "2009, 20011"?
I didn't even notice the typo in the pre-patch version - I have an emacs file save hook that auto-updates these lines. Fixed now.
ACK,
Pushed. Any review on 10-12 yet? -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

Fixing this involved some refactoring of common code out of domain_conf and nwfilter_conf into nwfilter_params. * src/conf/nwfilter_params.h (virNWFilterFormatParamAttributes): Adjust signature. * src/conf/nwfilter_params.c (_formatParameterAttrs) (virNWFilterFormatParamAttributes): Adjust indentation handling, and handle filterref here. (formatterParam): Delete unused struct. * src/conf/domain_conf.c (virDomainNetDefFormat): Adjust caller. * src/conf/nwfilter_conf.c (virNWFilterIncludeDefFormat): Likewise. --- src/conf/domain_conf.c | 15 ++++--------- src/conf/nwfilter_conf.c | 18 ++++++---------- src/conf/nwfilter_params.c | 45 +++++++++++++++++++------------------------ src/conf/nwfilter_params.h | 7 ++++- 4 files changed, 37 insertions(+), 48 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 70201af..efdf914 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -9441,7 +9441,6 @@ virDomainNetDefFormat(virBufferPtr buf, unsigned int flags) { const char *type = virDomainNetTypeToString(def->type); - char *attrs; if (!type) { virDomainReportError(VIR_ERR_INTERNAL_ERROR, @@ -9562,15 +9561,11 @@ virDomainNetDefFormat(virBufferPtr buf, } } if (def->filter) { - virBufferEscapeString(buf, " <filterref filter='%s'", - def->filter); - attrs = virNWFilterFormatParamAttributes(def->filterparams, - " "); - if (!attrs || strlen(attrs) <= 1) - virBufferAddLit(buf, "/>\n"); - else - virBufferAsprintf(buf, ">\n%s </filterref>\n", attrs); - VIR_FREE(attrs); + virBufferAdjustIndent(buf, 4); + if (virNWFilterFormatParamAttributes(buf, def->filterparams, + def->filter) < 0) + return -1; + virBufferAdjustIndent(buf, -4); } if (def->bootIndex) virBufferAsprintf(buf, " <boot order='%d'/>\n", def->bootIndex); diff --git a/src/conf/nwfilter_conf.c b/src/conf/nwfilter_conf.c index 08ede48..5ab4c60 100644 --- a/src/conf/nwfilter_conf.c +++ b/src/conf/nwfilter_conf.c @@ -2849,19 +2849,15 @@ no_memory: static char * virNWFilterIncludeDefFormat(virNWFilterIncludeDefPtr inc) { - char *attrs; virBuffer buf = VIR_BUFFER_INITIALIZER; - virBufferAsprintf(&buf," <filterref filter='%s'", - inc->filterref); - - attrs = virNWFilterFormatParamAttributes(inc->params, " "); - - if (!attrs || strlen(attrs) <= 1) - virBufferAddLit(&buf, "/>\n"); - else - virBufferAsprintf(&buf, ">\n%s </filterref>\n", attrs); - + virBufferAdjustIndent(&buf, 2); + if (virNWFilterFormatParamAttributes(&buf, inc->params, + inc->filterref) < 0) { + virBufferFreeAndReset(&buf); + return NULL; + } + virBufferAdjustIndent(&buf, -2); if (virBufferError(&buf)) { virReportOOMError(); virBufferFreeAndReset(&buf); diff --git a/src/conf/nwfilter_params.c b/src/conf/nwfilter_params.c index ee10b21..871aca9 100644 --- a/src/conf/nwfilter_params.c +++ b/src/conf/nwfilter_params.c @@ -258,41 +258,36 @@ skip_entry: } -struct formatterParam { - virBufferPtr buf; - const char *indent; -}; - - static void _formatParameterAttrs(void *payload, const void *name, void *data) { - struct formatterParam *fp = (struct formatterParam *)data; + virBufferPtr buf = data; - virBufferAsprintf(fp->buf, "%s<parameter name='%s' value='%s'/>\n", - fp->indent, + virBufferAsprintf(buf, " <parameter name='%s' value='%s'/>\n", (const char *)name, (char *)payload); } -char * -virNWFilterFormatParamAttributes(virNWFilterHashTablePtr table, - const char *indent) +int +virNWFilterFormatParamAttributes(virBufferPtr buf, + virNWFilterHashTablePtr table, + const char *filterref) { - virBuffer buf = VIR_BUFFER_INITIALIZER; - struct formatterParam fp = { - .buf = &buf, - .indent = indent, - }; - - virHashForEach(table->hashTable, _formatParameterAttrs, &fp); + int count = virHashSize(table->hashTable); - if (virBufferError(&buf)) { - virReportOOMError(); - virBufferFreeAndReset(&buf); - return NULL; + if (count < 0) { + virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("missing filter parameter table")); + return -1; } - - return virBufferContentAndReset(&buf); + virBufferAsprintf(buf, "<filterref filter='%s'", filterref); + if (count) { + virBufferAddLit(buf, ">\n"); + virHashForEach(table->hashTable, _formatParameterAttrs, buf); + virBufferAddLit(buf, "</filterref>\n"); + } else { + virBufferAddLit(buf, "/>\n"); + } + return 0; } diff --git a/src/conf/nwfilter_params.h b/src/conf/nwfilter_params.h index 012d6a1..4345229 100644 --- a/src/conf/nwfilter_params.h +++ b/src/conf/nwfilter_params.h @@ -1,6 +1,7 @@ /* * nwfilter_params.h: parsing and data maintenance of filter parameters * + * Copyright (C) 2011 Red Hat, Inc. * Copyright (C) 2010 IBM Corporation * * This library is free software; you can redistribute it and/or @@ -23,6 +24,7 @@ # define NWFILTER_PARAMS_H # include "hash.h" +# include "buf.h" typedef struct _virNWFilterHashTable virNWFilterHashTable; typedef virNWFilterHashTable *virNWFilterHashTablePtr; @@ -35,8 +37,9 @@ struct _virNWFilterHashTable { virNWFilterHashTablePtr virNWFilterParseParamAttributes(xmlNodePtr cur); -char * virNWFilterFormatParamAttributes(virNWFilterHashTablePtr table, - const char *indent); +int virNWFilterFormatParamAttributes(virBufferPtr buf, + virNWFilterHashTablePtr table, + const char *filterref); virNWFilterHashTablePtr virNWFilterHashTableCreate(int n); void virNWFilterHashTableFree(virNWFilterHashTablePtr table); -- 1.7.4.4

Dňa 29.9.2011 18:22, Eric Blake wrote / napísal(a):
Fixing this involved some refactoring of common code out of domain_conf and nwfilter_conf into nwfilter_params.
* src/conf/nwfilter_params.h (virNWFilterFormatParamAttributes): Adjust signature. * src/conf/nwfilter_params.c (_formatParameterAttrs) (virNWFilterFormatParamAttributes): Adjust indentation handling, and handle filterref here. (formatterParam): Delete unused struct. * src/conf/domain_conf.c (virDomainNetDefFormat): Adjust caller. * src/conf/nwfilter_conf.c (virNWFilterIncludeDefFormat): Likewise. --- src/conf/domain_conf.c | 15 ++++--------- src/conf/nwfilter_conf.c | 18 ++++++---------- src/conf/nwfilter_params.c | 45 +++++++++++++++++++------------------------ src/conf/nwfilter_params.h | 7 ++++- 4 files changed, 37 insertions(+), 48 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 70201af..efdf914 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c
@@ -9562,15 +9561,11 @@ virDomainNetDefFormat(virBufferPtr buf, } } if (def->filter) { - virBufferEscapeString(buf, "<filterref filter='%s'", - def->filter); - attrs = virNWFilterFormatParamAttributes(def->filterparams, - " ");
The offset of the <filterref element is 6 spaces and of NWFilter param attributes is 8 spaces here.
- if (!attrs || strlen(attrs)<= 1) - virBufferAddLit(buf, "/>\n"); - else - virBufferAsprintf(buf, ">\n%s</filterref>\n", attrs); - VIR_FREE(attrs); + virBufferAdjustIndent(buf, 4);
Here you add a offset of 4 (the param attributes are indented 6 spaces). This probably should be set to 6 as other elements in this function are indented 6 spaces. (Look into the original mail please, if you are checking this, whitespace in this reply is mangled by thunderbird ...)
+ if (virNWFilterFormatParamAttributes(buf, def->filterparams, + def->filter)< 0) + return -1; + virBufferAdjustIndent(buf, -4); } if (def->bootIndex) virBufferAsprintf(buf, "<boot order='%d'/>\n", def->bootIndex);
ACK with that fixed. Peter

On 10/21/2011 01:22 PM, Peter Krempa wrote:
Dňa 29.9.2011 18:22, Eric Blake wrote / napísal(a):
Fixing this involved some refactoring of common code out of domain_conf and nwfilter_conf into nwfilter_params.
@@ -9562,15 +9561,11 @@ virDomainNetDefFormat(virBufferPtr buf, } } if (def->filter) { - virBufferEscapeString(buf, "<filterref filter='%s'", - def->filter); - attrs = virNWFilterFormatParamAttributes(def->filterparams, - " ");
The offset of the <filterref element is 6 spaces and of NWFilter param attributes is 8 spaces here.
- if (!attrs || strlen(attrs)<= 1) - virBufferAddLit(buf, "/>\n"); - else - virBufferAsprintf(buf, ">\n%s</filterref>\n", attrs); - VIR_FREE(attrs); + virBufferAdjustIndent(buf, 4);
Here you add a offset of 4 (the param attributes are indented 6 spaces). This probably should be set to 6 as other elements in this function are indented 6 spaces. (Look into the original mail please, if you are checking this, whitespace in this reply is mangled by thunderbird ...)
No joke about the mangling :) (Honestly, how can ANYONE drag their feet for SOOOO long at applying a patch that has already been provided? https://bugzilla.mozilla.org/show_bug.cgi?id=456053) (And a corollary - why isn't Fedora picking up that patch into their builds of thunderbird, even if upstream is dragging their feet?) But you were right about needing 6, not 4. Fixed.
ACK with that fixed.
and pushed. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

Use auto-indent in more places. * src/conf/storage_encryption_conf.h (virStorageEncryptionFormat): Drop parameter. * src/conf/storage_encryption_conf.c (virStorageEncryptionFormat) (virStorageEncryptionSecretFormat): Simplify with auto-indent. * src/conf/domain_conf.c (virDomainDiskDefFormat): Adjust caller. * src/conf/storage_conf.c (virStorageVolTargetDefFormat): Likewise. --- src/conf/domain_conf.c | 9 ++++++--- src/conf/storage_conf.c | 9 ++++++--- src/conf/storage_encryption_conf.c | 20 ++++++++------------ src/conf/storage_encryption_conf.h | 5 ++--- 4 files changed, 22 insertions(+), 21 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index efdf914..6ab73ec 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -9221,9 +9221,12 @@ virDomainDiskDefFormat(virBufferPtr buf, if (def->serial) virBufferEscapeString(buf, " <serial>%s</serial>\n", def->serial); - if (def->encryption != NULL && - virStorageEncryptionFormat(buf, def->encryption, 6) < 0) - return -1; + if (def->encryption) { + virBufferAdjustIndent(buf, 6); + if (virStorageEncryptionFormat(buf, def->encryption) < 0) + return -1; + virBufferAdjustIndent(buf, -6); + } if (virDomainDeviceInfoFormat(buf, &def->info, flags) < 0) return -1; diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c index e893b2d..898db62 100644 --- a/src/conf/storage_conf.c +++ b/src/conf/storage_conf.c @@ -1204,9 +1204,12 @@ virStorageVolTargetDefFormat(virStorageVolOptionsPtr options, virBufferAddLit(buf," </permissions>\n"); - if (def->encryption != NULL && - virStorageEncryptionFormat(buf, def->encryption, 4) < 0) - return -1; + if (def->encryption) { + virBufferAdjustIndent(buf, 4); + if (virStorageEncryptionFormat(buf, def->encryption) < 0) + return -1; + virBufferAdjustIndent(buf, -4); + } virBufferAsprintf(buf, " </%s>\n", type); diff --git a/src/conf/storage_encryption_conf.c b/src/conf/storage_encryption_conf.c index 73e16ed..3208333 100644 --- a/src/conf/storage_encryption_conf.c +++ b/src/conf/storage_encryption_conf.c @@ -1,7 +1,7 @@ /* * storage_encryption_conf.c: volume encryption information * - * Copyright (C) 2009-2010 Red Hat, Inc. + * Copyright (C) 2009-2011 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -211,8 +211,7 @@ virStorageEncryptionParseNode(xmlDocPtr xml, xmlNodePtr root) static int virStorageEncryptionSecretFormat(virBufferPtr buf, - virStorageEncryptionSecretPtr secret, - int indent) + virStorageEncryptionSecretPtr secret) { const char *type; char uuidstr[VIR_UUID_STRING_BUFLEN]; @@ -225,15 +224,14 @@ virStorageEncryptionSecretFormat(virBufferPtr buf, } virUUIDFormat(secret->uuid, uuidstr); - virBufferAsprintf(buf, "%*s<secret type='%s' uuid='%s'/>\n", - indent, "", type, uuidstr); + virBufferAsprintf(buf, " <secret type='%s' uuid='%s'/>\n", + type, uuidstr); return 0; } int virStorageEncryptionFormat(virBufferPtr buf, - virStorageEncryptionPtr enc, - int indent) + virStorageEncryptionPtr enc) { const char *format; size_t i; @@ -244,16 +242,14 @@ virStorageEncryptionFormat(virBufferPtr buf, "%s", _("unexpected encryption format")); return -1; } - virBufferAsprintf(buf, "%*s<encryption format='%s'>\n", - indent, "", format); + virBufferAsprintf(buf, "<encryption format='%s'>\n", format); for (i = 0; i < enc->nsecrets; i++) { - if (virStorageEncryptionSecretFormat(buf, enc->secrets[i], - indent + 2) < 0) + if (virStorageEncryptionSecretFormat(buf, enc->secrets[i]) < 0) return -1; } - virBufferAsprintf(buf, "%*s</encryption>\n", indent, ""); + virBufferAddLit(buf, "</encryption>\n"); return 0; } diff --git a/src/conf/storage_encryption_conf.h b/src/conf/storage_encryption_conf.h index fa5f3cb..cfb088c 100644 --- a/src/conf/storage_encryption_conf.h +++ b/src/conf/storage_encryption_conf.h @@ -1,7 +1,7 @@ /* * storage_encryption_conf.h: volume encryption information * - * Copyright (C) 2009-2010 Red Hat, Inc. + * Copyright (C) 2009-2011 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -66,8 +66,7 @@ void virStorageEncryptionFree(virStorageEncryptionPtr enc); virStorageEncryptionPtr virStorageEncryptionParseNode(xmlDocPtr xml, xmlNodePtr root); int virStorageEncryptionFormat(virBufferPtr buf, - virStorageEncryptionPtr enc, - int indent); + virStorageEncryptionPtr enc); /* A helper for VIR_STORAGE_ENCRYPTION_FORMAT_QCOW */ enum { -- 1.7.4.4

Dňa 29.9.2011 18:22, Eric Blake wrote / napísal(a):
Use auto-indent in more places.
* src/conf/storage_encryption_conf.h (virStorageEncryptionFormat): Drop parameter. * src/conf/storage_encryption_conf.c (virStorageEncryptionFormat) (virStorageEncryptionSecretFormat): Simplify with auto-indent. * src/conf/domain_conf.c (virDomainDiskDefFormat): Adjust caller. * src/conf/storage_conf.c (virStorageVolTargetDefFormat): Likewise. --- src/conf/domain_conf.c | 9 ++++++--- src/conf/storage_conf.c | 9 ++++++--- src/conf/storage_encryption_conf.c | 20 ++++++++------------ src/conf/storage_encryption_conf.h | 5 ++--- 4 files changed, 22 insertions(+), 21 deletions(-)
ACK. Peter

On 10/21/2011 01:32 PM, Peter Krempa wrote:
Dňa 29.9.2011 18:22, Eric Blake wrote / napísal(a):
Use auto-indent in more places.
* src/conf/storage_encryption_conf.h (virStorageEncryptionFormat): Drop parameter. * src/conf/storage_encryption_conf.c (virStorageEncryptionFormat) (virStorageEncryptionSecretFormat): Simplify with auto-indent. * src/conf/domain_conf.c (virDomainDiskDefFormat): Adjust caller. * src/conf/storage_conf.c (virStorageVolTargetDefFormat): Likewise. --- src/conf/domain_conf.c | 9 ++++++--- src/conf/storage_conf.c | 9 ++++++--- src/conf/storage_encryption_conf.c | 20 ++++++++------------ src/conf/storage_encryption_conf.h | 5 ++--- 4 files changed, 22 insertions(+), 21 deletions(-)
ACK.
Finally pushed. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

Break some long lines, and use more efficient functions when possible, such as relying on virBufferEscapeString to skip output on a NULL arg. Ensure that output does not embed newlines, since auto-indent won't work in those situations. * src/conf/domain_conf.c (virDomainTimerDefFormat): Break output lines. (virDomainDefFormatInternal, virDomainDiskDefFormat) (virDomainActualNetDefFormat, virDomainNetDefFormat) (virDomainHostdevDefFormat): Minor cleanups. --- src/conf/domain_conf.c | 179 ++++++++++++++++++++++-------------------------- 1 files changed, 81 insertions(+), 98 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 6ab73ec..1871974 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -9146,7 +9146,7 @@ virDomainDiskDefFormat(virBufferPtr buf, if (def->driverName || def->driverType || def->cachemode || def->ioeventfd || def->event_idx) { - virBufferAsprintf(buf, " <driver"); + virBufferAddLit(buf, " <driver"); if (def->driverName) virBufferAsprintf(buf, " name='%s'", def->driverName); if (def->driverType) @@ -9161,7 +9161,7 @@ virDomainDiskDefFormat(virBufferPtr buf, virBufferAsprintf(buf, " ioeventfd='%s'", ioeventfd); if (def->event_idx) virBufferAsprintf(buf, " event_idx='%s'", event_idx); - virBufferAsprintf(buf, "/>\n"); + virBufferAddLit(buf, "/>\n"); } if (def->src || def->nhosts > 0) { @@ -9185,18 +9185,18 @@ virDomainDiskDefFormat(virBufferPtr buf, virBufferEscapeString(buf, " name='%s'", def->src); } if (def->nhosts == 0) { - virBufferAsprintf(buf, "/>\n"); + virBufferAddLit(buf, "/>\n"); } else { int i; - virBufferAsprintf(buf, ">\n"); + virBufferAddLit(buf, ">\n"); for (i = 0; i < def->nhosts; i++) { virBufferEscapeString(buf, " <host name='%s'", def->hosts[i].name); virBufferEscapeString(buf, " port='%s'/>\n", def->hosts[i].port); } - virBufferAsprintf(buf, " </source>\n"); + virBufferAddLit(buf, " </source>\n"); } break; default: @@ -9218,9 +9218,7 @@ virDomainDiskDefFormat(virBufferPtr buf, virBufferAddLit(buf, " <shareable/>\n"); if (def->transient) virBufferAddLit(buf, " <transient/>\n"); - if (def->serial) - virBufferEscapeString(buf, " <serial>%s</serial>\n", - def->serial); + virBufferEscapeString(buf, " <serial>%s</serial>\n", def->serial); if (def->encryption) { virBufferAdjustIndent(buf, 6); if (virStorageEncryptionFormat(buf, def->encryption) < 0) @@ -9398,10 +9396,8 @@ virDomainActualNetDefFormat(virBufferPtr buf, switch (def->type) { case VIR_DOMAIN_NET_TYPE_BRIDGE: - if (def->data.bridge.brname) { - virBufferEscapeString(buf, " <source bridge='%s'/>\n", - def->data.bridge.brname); - } + virBufferEscapeString(buf, " <source bridge='%s'/>\n", + def->data.bridge.brname); break; case VIR_DOMAIN_NET_TYPE_DIRECT: @@ -9462,10 +9458,8 @@ virDomainNetDefFormat(virBufferPtr buf, case VIR_DOMAIN_NET_TYPE_NETWORK: virBufferEscapeString(buf, " <source network='%s'", def->data.network.name); - if (def->data.network.portgroup) { - virBufferEscapeString(buf, " portgroup='%s'", - def->data.network.portgroup); - } + virBufferEscapeString(buf, " portgroup='%s'", + def->data.network.portgroup); virBufferAddLit(buf, "/>\n"); virBufferAdjustIndent(buf, 6); virVirtualPortProfileFormat(buf, def->data.network.virtPortProfile); @@ -9476,15 +9470,13 @@ virDomainNetDefFormat(virBufferPtr buf, break; case VIR_DOMAIN_NET_TYPE_ETHERNET: - if (def->data.ethernet.dev) - virBufferEscapeString(buf, " <source dev='%s'/>\n", - def->data.ethernet.dev); + virBufferEscapeString(buf, " <source dev='%s'/>\n", + def->data.ethernet.dev); if (def->data.ethernet.ipaddr) virBufferAsprintf(buf, " <ip address='%s'/>\n", def->data.ethernet.ipaddr); - if (def->data.ethernet.script) - virBufferEscapeString(buf, " <script path='%s'/>\n", - def->data.ethernet.script); + virBufferEscapeString(buf, " <script path='%s'/>\n", + def->data.ethernet.script); break; case VIR_DOMAIN_NET_TYPE_BRIDGE: @@ -9493,9 +9485,8 @@ virDomainNetDefFormat(virBufferPtr buf, if (def->data.bridge.ipaddr) virBufferAsprintf(buf, " <ip address='%s'/>\n", def->data.bridge.ipaddr); - if (def->data.bridge.script) - virBufferEscapeString(buf, " <script path='%s'/>\n", - def->data.bridge.script); + virBufferEscapeString(buf, " <script path='%s'/>\n", + def->data.bridge.script); break; case VIR_DOMAIN_NET_TYPE_SERVER: @@ -9518,7 +9509,7 @@ virDomainNetDefFormat(virBufferPtr buf, virBufferEscapeString(buf, " <source dev='%s'", def->data.direct.linkdev); virBufferAsprintf(buf, " mode='%s'", - virMacvtapModeTypeToString(def->data.direct.mode)); + virMacvtapModeTypeToString(def->data.direct.mode)); virBufferAddLit(buf, "/>\n"); virBufferAdjustIndent(buf, 6); virVirtualPortProfileFormat(buf, def->data.direct.virtPortProfile); @@ -9575,7 +9566,8 @@ virDomainNetDefFormat(virBufferPtr buf, if (def->tune.sndbuf_specified) { virBufferAddLit(buf, " <tune>\n"); - virBufferAsprintf(buf, " <sndbuf>%lu</sndbuf>\n", def->tune.sndbuf); + virBufferAsprintf(buf, " <sndbuf>%lu</sndbuf>\n", + def->tune.sndbuf); virBufferAddLit(buf, " </tune>\n"); } @@ -9613,7 +9605,7 @@ virDomainChrSourceDefFormat(virBufferPtr buf, return -1; } - /* Compat with legacy <console tty='/dev/pts/5'/> syntax */ + /* Compat with legacy <console tty='/dev/pts/5'/> syntax */ virBufferAsprintf(buf, " type='%s'", type); if (tty_compat) { virBufferEscapeString(buf, " tty='%s'", @@ -9784,8 +9776,7 @@ virDomainChrDefFormat(virBufferPtr buf, return -1; } - virBufferAsprintf(buf, " </%s>\n", - elementName); + virBufferAsprintf(buf, " </%s>\n", elementName); return ret; } @@ -9819,9 +9810,8 @@ virDomainSmartcardDefFormat(virBufferPtr buf, for (i = 0; i < VIR_DOMAIN_SMARTCARD_NUM_CERTIFICATES; i++) virBufferEscapeString(buf, " <certificate>%s</certificate>\n", def->data.cert.file[i]); - if (def->data.cert.database) - virBufferEscapeString(buf, " <database>%s</database>\n", - def->data.cert.database); + virBufferEscapeString(buf, " <database>%s</database>\n", + def->data.cert.database); break; case VIR_DOMAIN_SMARTCARD_TYPE_PASSTHROUGH: @@ -9854,8 +9844,7 @@ virDomainSoundDefFormat(virBufferPtr buf, return -1; } - virBufferAsprintf(buf, " <sound model='%s'", - model); + virBufferAsprintf(buf, " <sound model='%s'", model); if (virDomainDeviceInfoIsSet(&def->info, flags)) { virBufferAddLit(buf, ">\n"); @@ -9883,8 +9872,7 @@ virDomainMemballoonDefFormat(virBufferPtr buf, return -1; } - virBufferAsprintf(buf, " <memballoon model='%s'", - model); + virBufferAsprintf(buf, " <memballoon model='%s'", model); if (virDomainDeviceInfoIsSet(&def->info, flags)) { virBufferAddLit(buf, ">\n"); @@ -10098,7 +10086,8 @@ virDomainTimerDefFormat(virBufferPtr buf, && (def->catchup.limit == 0)) { virBufferAddLit(buf, "/>\n"); } else { - virBufferAddLit(buf, ">\n <catchup "); + virBufferAddLit(buf, ">\n"); + virBufferAddLit(buf, " <catchup "); if (def->catchup.threshold > 0) { virBufferAsprintf(buf, " threshold='%lu'", def->catchup.threshold); } @@ -10108,7 +10097,8 @@ virDomainTimerDefFormat(virBufferPtr buf, if (def->catchup.limit > 0) { virBufferAsprintf(buf, " limit='%lu'", def->catchup.limit); } - virBufferAddLit(buf, "/>\n </timer>\n"); + virBufferAddLit(buf, "/>\n"); + virBufferAddLit(buf, " </timer>\n"); } return 0; @@ -10396,7 +10386,8 @@ virDomainHostdevDefFormat(virBufferPtr buf, def->source.subsys.u.usb.bus, def->source.subsys.u.usb.device); } else if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) { - virBufferAsprintf(buf, " <address domain='0x%.4x' bus='0x%.2x' slot='0x%.2x' function='0x%.1x'/>\n", + virBufferAsprintf(buf, " <address domain='0x%.4x' bus='0x%.2x' " + "slot='0x%.2x' function='0x%.1x'/>\n", def->source.subsys.u.pci.domain, def->source.subsys.u.pci.bus, def->source.subsys.u.pci.slot, @@ -10449,8 +10440,8 @@ virDomainRedirdevDefFormat(virBufferPtr buf, static int virDomainHubDefFormat(virBufferPtr buf, - virDomainHubDefPtr def, - unsigned int flags) + virDomainHubDefPtr def, + unsigned int flags) { const char *type = virDomainHubTypeToString(def->type); @@ -10525,9 +10516,8 @@ virDomainDefFormatInternal(virDomainDefPtr def, virUUIDFormat(uuid, uuidstr); virBufferAsprintf(buf, " <uuid>%s</uuid>\n", uuidstr); - if (def->description) - virBufferEscapeString(buf, " <description>%s</description>\n", - def->description); + virBufferEscapeString(buf, " <description>%s</description>\n", + def->description); virBufferAsprintf(buf, " <memory>%lu</memory>\n", def->mem.max_balloon); virBufferAsprintf(buf, " <currentMemory>%lu</currentMemory>\n", @@ -10535,16 +10525,16 @@ virDomainDefFormatInternal(virDomainDefPtr def, /* add blkiotune only if there are any */ if (def->blkio.weight) { - virBufferAsprintf(buf, " <blkiotune>\n"); + virBufferAddLit(buf, " <blkiotune>\n"); virBufferAsprintf(buf, " <weight>%u</weight>\n", def->blkio.weight); - virBufferAsprintf(buf, " </blkiotune>\n"); + virBufferAddLit(buf, " </blkiotune>\n"); } /* add memtune only if there are any */ if (def->mem.hard_limit || def->mem.soft_limit || def->mem.min_guarantee || def->mem.swap_hard_limit) - virBufferAsprintf(buf, " <memtune>\n"); + virBufferAddLit(buf, " <memtune>\n"); if (def->mem.hard_limit) { virBufferAsprintf(buf, " <hard_limit>%lu</hard_limit>\n", def->mem.hard_limit); @@ -10563,12 +10553,12 @@ virDomainDefFormatInternal(virDomainDefPtr def, } if (def->mem.hard_limit || def->mem.soft_limit || def->mem.min_guarantee || def->mem.swap_hard_limit) - virBufferAsprintf(buf, " </memtune>\n"); + virBufferAddLit(buf, " </memtune>\n"); if (def->mem.hugepage_backed) { - virBufferAddLit(buf, " <memoryBacking>\n"); - virBufferAddLit(buf, " <hugepages/>\n"); - virBufferAddLit(buf, " </memoryBacking>\n"); + virBufferStrcat(buf, " <memoryBacking>\n", + " <hugepages/>\n", + " </memoryBacking>\n", NULL); } for (n = 0 ; n < def->cpumasklen ; n++) @@ -10626,27 +10616,25 @@ virDomainDefFormatInternal(virDomainDefPtr def, def->cputune.period || def->cputune.quota) virBufferAddLit(buf, " </cputune>\n"); - if (def->numatune.memory.nodemask) - virBufferAddLit(buf, " <numatune>\n"); - if (def->numatune.memory.nodemask) { char *nodemask = NULL; + + virBufferAddLit(buf, " <numatune>\n"); nodemask = virDomainCpuSetFormat(def->numatune.memory.nodemask, VIR_DOMAIN_CPUMASK_LEN); if (nodemask == NULL) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("failed to format nodeset for NUMA memory tuning")); + virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("failed to format nodeset for NUMA memory tuning")); goto cleanup; } virBufferAsprintf(buf, " <memory mode='%s' nodeset='%s'/>\n", - virDomainNumatuneMemModeTypeToString(def->numatune.memory.mode), + virDomainNumatuneMemModeTypeToString(def->numatune. + memory.mode), nodemask); VIR_FREE(nodemask); - } - - if (def->numatune.memory.nodemask) virBufferAddLit(buf, " </numatune>\n"); + } if (def->sysinfo) virDomainSysinfoDefFormat(buf, def->sysinfo); @@ -10654,12 +10642,12 @@ virDomainDefFormatInternal(virDomainDefPtr def, if (def->os.bootloader) { virBufferEscapeString(buf, " <bootloader>%s</bootloader>\n", def->os.bootloader); - if (def->os.bootloaderArgs) - virBufferEscapeString(buf, " <bootloader_args>%s</bootloader_args>\n", - def->os.bootloaderArgs); + virBufferEscapeString(buf, + " <bootloader_args>%s</bootloader_args>\n", + def->os.bootloaderArgs); } - virBufferAddLit(buf, " <os>\n"); + virBufferAddLit(buf, " <os>\n"); virBufferAddLit(buf, " <type"); if (def->os.arch) virBufferAsprintf(buf, " arch='%s'", def->os.arch); @@ -10676,24 +10664,18 @@ virDomainDefFormatInternal(virDomainDefPtr def, else virBufferAsprintf(buf, ">%s</type>\n", def->os.type); - if (def->os.init) - virBufferEscapeString(buf, " <init>%s</init>\n", - def->os.init); - if (def->os.loader) - virBufferEscapeString(buf, " <loader>%s</loader>\n", - def->os.loader); - if (def->os.kernel) - virBufferEscapeString(buf, " <kernel>%s</kernel>\n", - def->os.kernel); - if (def->os.initrd) - virBufferEscapeString(buf, " <initrd>%s</initrd>\n", - def->os.initrd); - if (def->os.cmdline) - virBufferEscapeString(buf, " <cmdline>%s</cmdline>\n", - def->os.cmdline); - if (def->os.root) - virBufferEscapeString(buf, " <root>%s</root>\n", - def->os.root); + virBufferEscapeString(buf, " <init>%s</init>\n", + def->os.init); + virBufferEscapeString(buf, " <loader>%s</loader>\n", + def->os.loader); + virBufferEscapeString(buf, " <kernel>%s</kernel>\n", + def->os.kernel); + virBufferEscapeString(buf, " <initrd>%s</initrd>\n", + def->os.initrd); + virBufferEscapeString(buf, " <cmdline>%s</cmdline>\n", + def->os.cmdline); + virBufferEscapeString(buf, " <root>%s</root>\n", + def->os.root); if (!def->os.bootloader) { for (n = 0 ; n < def->os.nBootDevs ; n++) { @@ -10763,7 +10745,8 @@ virDomainDefFormatInternal(virDomainDefPtr def, virDomainClockOffsetTypeToString(def->clock.offset)); switch (def->clock.offset) { case VIR_DOMAIN_CLOCK_OFFSET_VARIABLE: - virBufferAsprintf(buf, " adjustment='%lld'", def->clock.data.adjustment); + virBufferAsprintf(buf, " adjustment='%lld'", + def->clock.data.adjustment); break; case VIR_DOMAIN_CLOCK_OFFSET_TIMEZONE: virBufferEscapeString(buf, " timezone='%s'", def->clock.data.timezone); @@ -10795,9 +10778,8 @@ virDomainDefFormatInternal(virDomainDefPtr def, virBufferAddLit(buf, " <devices>\n"); - if (def->emulator) - virBufferEscapeString(buf, " <emulator>%s</emulator>\n", - def->emulator); + virBufferEscapeString(buf, " <emulator>%s</emulator>\n", + def->emulator); for (n = 0 ; n < def->ndisks ; n++) if (virDomainDiskDefFormat(buf, def->disks[n], flags) < 0) @@ -10893,10 +10875,10 @@ virDomainDefFormatInternal(virDomainDefPtr def, goto cleanup; if (def->watchdog) - virDomainWatchdogDefFormat (buf, def->watchdog, flags); + virDomainWatchdogDefFormat(buf, def->watchdog, flags); if (def->memballoon) - virDomainMemballoonDefFormat (buf, def->memballoon, flags); + virDomainMemballoonDefFormat(buf, def->memballoon, flags); virBufferAddLit(buf, " </devices>\n"); @@ -10910,18 +10892,19 @@ virDomainDefFormatInternal(virDomainDefPtr def, (flags & VIR_DOMAIN_XML_INACTIVE)) { /* This is the default for inactive xml, so nothing to output. */ } else { - virBufferAsprintf(buf, " <seclabel type='%s' model='%s' relabel='%s'>\n", + virBufferAsprintf(buf, " <seclabel type='%s' model='%s' " + "relabel='%s'>\n", sectype, def->seclabel.model, def->seclabel.norelabel ? "no" : "yes"); - if (def->seclabel.label) - virBufferEscapeString(buf, " <label>%s</label>\n", - def->seclabel.label); - if (!def->seclabel.norelabel && def->seclabel.imagelabel) - virBufferEscapeString(buf, " <imagelabel>%s</imagelabel>\n", + virBufferEscapeString(buf, " <label>%s</label>\n", + def->seclabel.label); + if (!def->seclabel.norelabel) + virBufferEscapeString(buf, + " <imagelabel>%s</imagelabel>\n", def->seclabel.imagelabel); - if (def->seclabel.baselabel && - (def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC)) - virBufferEscapeString(buf, " <baselabel>%s</baselabel>\n", + if (def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC) + virBufferEscapeString(buf, + " <baselabel>%s</baselabel>\n", def->seclabel.baselabel); virBufferAddLit(buf, " </seclabel>\n"); } -- 1.7.4.4

Dňa 29.9.2011 18:22, Eric Blake wrote / napísal(a):
Break some long lines, and use more efficient functions when possible, such as relying on virBufferEscapeString to skip output on a NULL arg. Ensure that output does not embed newlines, since auto-indent won't work in those situations.
* src/conf/domain_conf.c (virDomainTimerDefFormat): Break output lines. (virDomainDefFormatInternal, virDomainDiskDefFormat) (virDomainActualNetDefFormat, virDomainNetDefFormat) (virDomainHostdevDefFormat): Minor cleanups. --- src/conf/domain_conf.c | 179 ++++++++++++++++++++++-------------------------- 1 files changed, 81 insertions(+), 98 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 6ab73ec..1871974 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -9476,15 +9470,13 @@ virDomainNetDefFormat(virBufferPtr buf, break;
case VIR_DOMAIN_NET_TYPE_ETHERNET: - if (def->data.ethernet.dev) - virBufferEscapeString(buf, "<source dev='%s'/>\n", - def->data.ethernet.dev); + virBufferEscapeString(buf, "<source dev='%s'/>\n", + def->data.ethernet.dev); if (def->data.ethernet.ipaddr) virBufferAsprintf(buf, "<ip address='%s'/>\n", def->data.ethernet.ipaddr);
This looks like it could be changed to virBufferEscapeString and drop the test. (or is the ip address being mangled by the escape function?)
- if (def->data.ethernet.script) - virBufferEscapeString(buf, "<script path='%s'/>\n", - def->data.ethernet.script); + virBufferEscapeString(buf, "<script path='%s'/>\n", + def->data.ethernet.script); break;
case VIR_DOMAIN_NET_TYPE_BRIDGE:
@@ -10563,12 +10553,12 @@ virDomainDefFormatInternal(virDomainDefPtr def, } if (def->mem.hard_limit || def->mem.soft_limit || def->mem.min_guarantee || def->mem.swap_hard_limit) - virBufferAsprintf(buf, "</memtune>\n"); + virBufferAddLit(buf, "</memtune>\n");
if (def->mem.hugepage_backed) { - virBufferAddLit(buf, "<memoryBacking>\n"); - virBufferAddLit(buf, "<hugepages/>\n"); - virBufferAddLit(buf, "</memoryBacking>\n");
I'd probably break the first string on a new line too, to have them nicely lined up.
+ virBufferStrcat(buf, "<memoryBacking>\n", + "<hugepages/>\n", + "</memoryBacking>\n", NULL); }
for (n = 0 ; n< def->cpumasklen ; n++) @@ -10626,27 +10616,25 @@ virDomainDefFormatInternal(virDomainDefPtr def, def->cputune.period || def->cputune.quota) virBufferAddLit(buf, "</cputune>\n");
- if (def->numatune.memory.nodemask) - virBufferAddLit(buf, "<numatune>\n"); - if (def->numatune.memory.nodemask) { char *nodemask = NULL; + + virBufferAddLit(buf, "<numatune>\n"); nodemask = virDomainCpuSetFormat(def->numatune.memory.nodemask, VIR_DOMAIN_CPUMASK_LEN); if (nodemask == NULL) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("failed to format nodeset for NUMA memory tuning")); + virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("failed to format nodeset for NUMA memory tuning")); goto cleanup; }
virBufferAsprintf(buf, "<memory mode='%s' nodeset='%s'/>\n", - virDomainNumatuneMemModeTypeToString(def->numatune.memory.mode), + virDomainNumatuneMemModeTypeToString(def->numatune. + memory.mode),
They shoul have made terminals with more than 80 cols at the very beginning :( This looked a little bit confusing to me at first, interpreting the dot as a comma ... but, well, it works.
nodemask); VIR_FREE(nodemask); - } - - if (def->numatune.memory.nodemask) virBufferAddLit(buf, "</numatune>\n"); + }
if (def->sysinfo) virDomainSysinfoDefFormat(buf, def->sysinfo);
ACK, you can safely ignore my comments to this patch, as they don't address any important issues :). I was looking for 13/13, but couldn't find one, so I suppose this is the last one. Peter

On 10/21/2011 02:08 PM, Peter Krempa wrote:
- if (def->data.ethernet.dev) - virBufferEscapeString(buf, "<source dev='%s'/>\n", - def->data.ethernet.dev); + virBufferEscapeString(buf, "<source dev='%s'/>\n", + def->data.ethernet.dev); if (def->data.ethernet.ipaddr) virBufferAsprintf(buf, "<ip address='%s'/>\n", def->data.ethernet.ipaddr);
This looks like it could be changed to virBufferEscapeString and drop the test. (or is the ip address being mangled by the escape function?)
virBufferEscapeString prints nothing if the last argument is NULL. Some of the code uses that as a nice side-effect so that "blah%s" omits blah if the string is also absent. But virBufferAsprintf can't take that shortcut - it's a var-arg function, and besides, how do you know whether someone meant to pass NULL for %p vs. trying to pass NULL to bypass output? I suppose I could convert some if(string)virBufferAsprintf(,string) to the simpler virBufferEscapeString(string), although it feels weird calling virBufferEscapeString for its side effect of omitting output when string is NULL, when there is nothing in the string that will be escaped. But I'd rather save that for a separate patch.
virBufferAsprintf(buf, "<memory mode='%s' nodeset='%s'/>\n", - virDomainNumatuneMemModeTypeToString(def->numatune.memory.mode), + virDomainNumatuneMemModeTypeToString(def->numatune. + memory.mode),
They shoul have made terminals with more than 80 cols at the very beginning :( This looked a little bit confusing to me at first, interpreting the dot as a comma ... but, well, it works.
Good point on readability - I could move the . to the front of the line: blah(dev->numatune .memory.mode) or use a temporary variable, to avoid the confusion.
ACK, you can safely ignore my comments to this patch, as they don't address any important issues :). I was looking for 13/13, but couldn't find one, so I suppose this is the last one.
13/13 exists, but I don't want to apply it, so it doesn't hurt my feelings if you don't review it: https://www.redhat.com/archives/libvir-list/2011-September/msg01267.html -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On 10/21/2011 02:08 PM, Peter Krempa wrote:
Dňa 29.9.2011 18:22, Eric Blake wrote / napísal(a):
Break some long lines, and use more efficient functions when possible, such as relying on virBufferEscapeString to skip output on a NULL arg. Ensure that output does not embed newlines, since auto-indent won't work in those situations.
* src/conf/domain_conf.c (virDomainTimerDefFormat): Break output lines. (virDomainDefFormatInternal, virDomainDiskDefFormat) (virDomainActualNetDefFormat, virDomainNetDefFormat) (virDomainHostdevDefFormat): Minor cleanups. ---
if (def->mem.hugepage_backed) { - virBufferAddLit(buf, "<memoryBacking>\n"); - virBufferAddLit(buf, "<hugepages/>\n"); - virBufferAddLit(buf, "</memoryBacking>\n");
I'd probably break the first string on a new line too, to have them nicely lined up.
+ virBufferStrcat(buf, "<memoryBacking>\n", + "<hugepages/>\n", + "</memoryBacking>\n", NULL); }
Done.
virBufferAsprintf(buf, "<memory mode='%s' nodeset='%s'/>\n", - virDomainNumatuneMemModeTypeToString(def->numatune.memory.mode), + virDomainNumatuneMemModeTypeToString(def->numatune. + memory.mode),
They shoul have made terminals with more than 80 cols at the very beginning :( This looked a little bit confusing to me at first, interpreting the dot as a comma ... but, well, it works.
I improved that one as well.
ACK, you can safely ignore my comments to this patch, as they don't address any important issues :).
Pushed. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

Future patches can take advantage of this to generate nicer XML output with parameterizable indentation. * src/util/buf.h (virBufferIndentAdd, virBufferIndentAddLit) (virBufferIndentAsprintf, 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, virBufferIndentAsprintf): New functions. * tests/virbuftest.c (testBufIndentation): Test it. --- At this point, since no one else is using these functions, I'm inclined to ditch this patch. I'm posting it only for completeness, since it added virBufferIndentAsprintf, and since it took quite a bit of reshuffling to rebase this on top of the auto-indent stuff. src/libvirt_private.syms | 3 ++ src/util/buf.c | 90 +++++++++++++++++++++++++++++++++++++++------- src/util/buf.h | 12 ++++++ tests/virbuftest.c | 52 +++++++++++++++++++++++---- 4 files changed, 137 insertions(+), 20 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 89cd6da..6505eae 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -30,6 +30,9 @@ virBufferEscapeSexpr; virBufferEscapeString; virBufferFreeAndReset; virBufferGetIndent; +virBufferIndentAdd; +virBufferIndentAsprintf; +virBufferIndentEscapeString; virBufferStrcat; virBufferURIEncodeString; virBufferUse; diff --git a/src/util/buf.c b/src/util/buf.c index b409de4..d4c4bcc 100644 --- a/src/util/buf.c +++ b/src/util/buf.c @@ -123,28 +123,34 @@ virBufferGrow(virBufferPtr buf, unsigned int len) } /** - * virBufferAdd: + * virBufferIndentAdd: * @buf: the buffer to append to - * @str: the string - * @len: the number of bytes to add, or -1 + * @indent: amount of explicit 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. Auto indentation may be applied. + * Add indentation (both from @indent and any auto-indent), 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(virBufferPtr buf, int indent, + const char *str, int len) { unsigned int needSize; - int indent; - if (!str || !buf || (len == 0 && buf->indent == 0)) + if (!str || !buf || (len == 0 && indent == 0)) return; if (buf->error) return; - indent = virBufferGetIndent(buf, true); + if (indent < 0 || INT_MAX - indent < buf->indent) { + virBufferSetError(buf, -1); + return; + } + indent += virBufferGetIndent(buf, true); if (len < 0) len = strlen(str); @@ -161,6 +167,22 @@ virBufferAdd(const virBufferPtr buf, const char *str, int len) } /** + * virBufferAdd: + * @buf: the buffer to append 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. Auto indentation may be applied. + * + */ +void +virBufferAdd(const virBufferPtr buf, const char *str, int len) +{ + virBufferIndentAdd(buf, 0, str, len); +} + +/** * virBufferAddChar: * @buf: the buffer to append to * @c: the character to add @@ -171,7 +193,7 @@ virBufferAdd(const virBufferPtr buf, const char *str, int len) void virBufferAddChar(virBufferPtr buf, char c) { - virBufferAdd(buf, &c, 1); + virBufferIndentAdd(buf, 0, &c, 1); } /** @@ -265,6 +287,27 @@ virBufferAsprintf(virBufferPtr buf, const char *format, ...) } /** + * virBufferIndentAsprintf: + * @buf: the buffer to append to + * @indent: amount of explicit indentation + * @format: the format + * @...: the variable list of arguments + * + * Do a formatted print to an XML buffer, with leading indentation + * (both from @indent and any auto-indentation). + */ +void +virBufferIndentAsprintf(virBufferPtr buf, int indent, + const char *format, ...) +{ + va_list argptr; + va_start(argptr, format); + virBufferIndentAdd(buf, indent, "", 0); + virBufferVasprintf(buf, format, argptr); + va_end(argptr); +} + +/** * virBufferVasprintf: * @buf: the buffer to append to * @format: the format @@ -285,7 +328,7 @@ virBufferVasprintf(virBufferPtr buf, const char *format, va_list argptr) return; if (buf->indent) - virBufferAdd(buf, "", -1); + virBufferIndentAdd(buf, 0, "", -1); if (buf->size == 0 && virBufferGrow(buf, 100) < 0) @@ -409,6 +452,27 @@ virBufferEscapeString(virBufferPtr buf, const char *format, const char *str) } /** + * virBufferIndentEscapeString: + * @buf: the buffer to append to + * @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 (both from @indent and auto-indent). The single + * %s string is escaped to form valid XML. + */ +void +virBufferIndentEscapeString(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 append to * @format: a printf like format string but with only one %s parameter @@ -489,7 +553,7 @@ virBufferURIEncodeString(virBufferPtr buf, const char *str) return; if (buf->indent) - virBufferAdd(buf, "", -1); + virBufferIndentAdd(buf, 0, "", -1); for (p = str; *p; ++p) { if (c_isalnum(*p)) @@ -534,6 +598,6 @@ virBufferStrcat(virBufferPtr buf, ...) va_start(ap, buf); while ((str = va_arg(ap, char *)) != NULL) - virBufferAdd(buf, str, -1); + virBufferIndentAdd(buf, 0, str, -1); va_end(ap); } diff --git a/src/util/buf.h b/src/util/buf.h index 08cb727..d913c69 100644 --- a/src/util/buf.h +++ b/src/util/buf.h @@ -61,4 +61,16 @@ void virBufferURIEncodeString(virBufferPtr buf, const char *str); void virBufferAdjustIndent(virBufferPtr buf, int indent); int virBufferGetIndent(const virBufferPtr buf, bool dynamic); +void virBufferIndentAdd(virBufferPtr buf, int indent, + const char *str, int len); +void virBufferIndentEscapeString(virBufferPtr buf, int indent, + const char *format, const char *str); +void virBufferIndentAsprintf(virBufferPtr buf, int indent, + const char *format, ...) + ATTRIBUTE_FMT_PRINTF(3, 4); + +# define virBufferIndentAddLit(buf_, indent_, literal_string_) \ + virBufferIndentAdd(buf_, indent_, "" literal_string_ "", \ + sizeof literal_string_ - 1) + #endif /* __VIR_BUFFER_H__ */ diff --git a/tests/virbuftest.c b/tests/virbuftest.c index 2f94e1c..a6dd84a 100644 --- a/tests/virbuftest.c +++ b/tests/virbuftest.c @@ -58,12 +58,44 @@ 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 & e"; + 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", "&"); + virBufferIndentAsprintf(buf, 1, "%s%s", "", ""); + virBufferIndentAsprintf(buf, 1, "%c", 'e'); + + result = virBufferContentAndReset(buf); + if (!result || STRNEQ(result, expected)) { + virtTestDifference(stderr, expected, result); + ret = -1; + } + VIR_FREE(result); + return ret; +} + static int testBufAutoIndent(const void *data ATTRIBUTE_UNUSED) { virBuffer bufinit = VIR_BUFFER_INITIALIZER; virBufferPtr buf = &bufinit; const char expected[] = - " 1\n 2\n 3\n 4\n 5\n 6\n 7\n &\n 8\n 9\n"; + " 1\n 2\n 3\n 4\n 5\n 6 7\n 8\n 9\n 10\n" + " <\n 11\n >\n 12\n 13\n"; char *result = NULL; int ret = 0; @@ -111,13 +143,18 @@ static int testBufAutoIndent(const void *data ATTRIBUTE_UNUSED) virBufferAdd(buf, "" "2\n", -1); /* Extra "" appeases syntax-check */ virBufferAddChar(buf, '3'); virBufferAddChar(buf, '\n'); - virBufferAsprintf(buf, "%d", 4); + virBufferIndentAdd(buf, 2, "4\n", 2); + virBufferAsprintf(buf, "%d", 5); virBufferAsprintf(buf, "%c", '\n'); - virBufferStrcat(buf, "5", "\n", "6\n", NULL); - virBufferEscapeString(buf, "%s\n", "7"); - virBufferEscapeString(buf, "%s\n", "&"); - virBufferEscapeSexpr(buf, "%s", "8\n"); - virBufferURIEncodeString(buf, "9"); + virBufferIndentAsprintf(buf, 2, "%s", "6"); + virBufferIndentAsprintf(buf, 2, "%s\n", "7"); + virBufferStrcat(buf, "8", "\n", "9\n", NULL); + virBufferEscapeString(buf, "%s\n", "10"); + virBufferEscapeString(buf, "%s\n", "<"); + virBufferIndentEscapeString(buf, 2, "%s\n", "11"); + virBufferIndentEscapeString(buf, 2, "%s\n", ">"); + virBufferEscapeSexpr(buf, "%s", "12\n"); + virBufferURIEncodeString(buf, "13"); virBufferAddChar(buf, '\n'); result = virBufferContentAndReset(buf); @@ -144,6 +181,7 @@ mymain(void) DO_TEST("EscapeString infinite loop", testBufInfiniteLoop, 1); DO_TEST("VSprintf infinite loop", testBufInfiniteLoop, 0); + DO_TEST("Indentation", testBufIndentation, 0); DO_TEST("Auto-indentation", testBufAutoIndent, 0); return(ret==0 ? EXIT_SUCCESS : EXIT_FAILURE); -- 1.7.4.4
participants (4)
-
Daniel P. Berrange
-
Eric Blake
-
Hai Dong Li
-
Peter Krempa