buf: support peeking at string contents

Right now, the only way to get at the contents of a virBuffer is
to destroy it.  But there are cases in my upcoming patches where
peeking at the contents makes life easier.  I suppose this does
open up the potential for bad code to dereference a stale pointer,
by disregarding the docs that the return value is invalid on the
next virBuf operation, but such is life.

* src/util/buf.h (virBufferCurrentContent): New declaration.
* src/util/buf.c (virBufferCurrentContent): Implement it.
* src/libvirt_private.syms (buf.h): Export it.
* tests/virbuftest.c (testBufAutoIndent): Test it.
This commit is contained in:
Eric Blake 2012-06-08 13:50:23 -06:00
parent 539e9b34b9
commit 9202f2c220
4 changed files with 31 additions and 1 deletions

View File

@ -20,6 +20,7 @@ virBufferAddChar;
virBufferAdjustIndent; virBufferAdjustIndent;
virBufferAsprintf; virBufferAsprintf;
virBufferContentAndReset; virBufferContentAndReset;
virBufferCurrentContent;
virBufferError; virBufferError;
virBufferEscape; virBufferEscape;
virBufferEscapeSexpr; virBufferEscapeSexpr;

View File

@ -174,13 +174,33 @@ virBufferAddChar(virBufferPtr buf, char c)
virBufferAdd(buf, &c, 1); virBufferAdd(buf, &c, 1);
} }
/**
* virBufferCurrentContent:
* @buf: Buffer
*
* Get the current content from the buffer. The content is only valid
* until the next operation on @buf, and an empty string is returned if
* no content is present yet.
*
* Returns the buffer content or NULL in case of error.
*/
const char *
virBufferCurrentContent(virBufferPtr buf)
{
if (!buf || buf->error)
return NULL;
return buf->use ? buf->content : "";
}
/** /**
* virBufferContentAndReset: * virBufferContentAndReset:
* @buf: Buffer * @buf: Buffer
* *
* Get the content from the buffer and free (only) the buffer structure. * Get the content from the buffer and free (only) the buffer structure.
* The caller owns the returned string & should free it when no longer * The caller owns the returned string & should free it when no longer
* required. The buffer object is reset to its initial state. * required. The buffer object is reset to its initial state. This
* interface intentionally returns NULL instead of an empty string if
* there is no content.
* *
* Returns the buffer content or NULL in case of error. * Returns the buffer content or NULL in case of error.
*/ */

View File

@ -37,6 +37,7 @@ struct _virBuffer {
}; };
# endif # endif
const char *virBufferCurrentContent(virBufferPtr buf);
char *virBufferContentAndReset(virBufferPtr buf); char *virBufferContentAndReset(virBufferPtr buf);
void virBufferFreeAndReset(virBufferPtr buf); void virBufferFreeAndReset(virBufferPtr buf);
int virBufferError(const virBufferPtr buf); int virBufferError(const virBufferPtr buf);

View File

@ -73,6 +73,10 @@ static int testBufAutoIndent(const void *data ATTRIBUTE_UNUSED)
ret = -1; ret = -1;
} }
virBufferAdjustIndent(buf, 3); virBufferAdjustIndent(buf, 3);
if (STRNEQ(virBufferCurrentContent(buf), "")) {
TEST_ERROR("Wrong content");
ret = -1;
}
if (virBufferGetIndent(buf, false) != 3 || if (virBufferGetIndent(buf, false) != 3 ||
virBufferGetIndent(buf, true) != 3 || virBufferGetIndent(buf, true) != 3 ||
virBufferError(buf)) { virBufferError(buf)) {
@ -102,6 +106,10 @@ static int testBufAutoIndent(const void *data ATTRIBUTE_UNUSED)
} }
virBufferAdjustIndent(buf, 2); virBufferAdjustIndent(buf, 2);
virBufferAddLit(buf, "1"); virBufferAddLit(buf, "1");
if (STRNEQ(virBufferCurrentContent(buf), " 1")) {
TEST_ERROR("Wrong content");
ret = -1;
}
if (virBufferGetIndent(buf, false) != 2 || if (virBufferGetIndent(buf, false) != 2 ||
virBufferGetIndent(buf, true) != 0) { virBufferGetIndent(buf, true) != 0) {
TEST_ERROR("Wrong indentation"); TEST_ERROR("Wrong indentation");