mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 13:45:38 +00:00
virBuffer: add way to trim back extra text
I'm tired of writing: bool sep = false; while (...) { if (sep) virBufferAddChar(buf, ','); sep = true; virBufferAdd(buf, str); } This makes it easier, allowing one to write: while (...) virBufferAsprintf(buf, "%s,", str); virBufferTrim(buf, ",", -1); to trim any remaining comma. * src/util/buf.h (virBufferTrim): Declare. * src/util/buf.c (virBufferTrim): New function. * tests/virbuftest.c (testBufTrim): Test it.
This commit is contained in:
parent
74951eadef
commit
cdb87b1c4b
@ -612,3 +612,39 @@ virBufferStrcat(virBufferPtr buf, ...)
|
||||
virBufferAdd(buf, str, -1);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/**
|
||||
* virBufferTrim:
|
||||
* @buf: the buffer to trim
|
||||
* @str: the optional string, to force an exact trim
|
||||
* @len: the number of bytes to trim, or -1 to use @str
|
||||
*
|
||||
* Trim the tail of a buffer. If @str is provided, the trim only occurs
|
||||
* if the current tail of the buffer matches @str; a non-negative @len
|
||||
* further limits how much of the tail is trimmed. If @str is NULL, then
|
||||
* @len must be non-negative.
|
||||
*
|
||||
* Returns -1 if @buf has previously encountered an error or if @len is
|
||||
* invalid, 0 if there was nothing to trim (@buf was too short or @str
|
||||
* didn't match), and 1 if the trim was successful.
|
||||
*/
|
||||
int
|
||||
virBufferTrim(virBufferPtr buf, const char *str, int len)
|
||||
{
|
||||
size_t len2 = 0;
|
||||
|
||||
if (!buf || buf->error || (!str && len < 0))
|
||||
return -1;
|
||||
|
||||
if (len > 0 && len > buf->use)
|
||||
return 0;
|
||||
if (str) {
|
||||
len2 = strlen(str);
|
||||
if (len2 > buf->use ||
|
||||
memcmp(&buf->content[buf->use - len2], str, len2) != 0)
|
||||
return 0;
|
||||
}
|
||||
buf->use -= len < 0 ? len2 : len;
|
||||
buf->content[buf->use] = '\0';
|
||||
return 1;
|
||||
}
|
||||
|
@ -64,4 +64,6 @@ void virBufferURIEncodeString(virBufferPtr buf, const char *str);
|
||||
void virBufferAdjustIndent(virBufferPtr buf, int indent);
|
||||
int virBufferGetIndent(const virBufferPtr buf, bool dynamic);
|
||||
|
||||
int virBufferTrim(virBufferPtr buf, const char *trim, int len);
|
||||
|
||||
#endif /* __VIR_BUFFER_H__ */
|
||||
|
@ -133,6 +133,61 @@ static int testBufAutoIndent(const void *data ATTRIBUTE_UNUSED)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int testBufTrim(const void *data ATTRIBUTE_UNUSED)
|
||||
{
|
||||
virBuffer bufinit = VIR_BUFFER_INITIALIZER;
|
||||
virBufferPtr buf = NULL;
|
||||
char *result = NULL;
|
||||
const char *expected = "a,b";
|
||||
int ret = -1;
|
||||
int i = 1;
|
||||
|
||||
#define ACT(str, len, result) \
|
||||
do { \
|
||||
if (virBufferTrim(buf, str, len) != result) { \
|
||||
TEST_ERROR("trim %d failed", i); \
|
||||
goto cleanup; \
|
||||
} \
|
||||
i++; \
|
||||
} while (0);
|
||||
|
||||
if (virBufferTrim(buf, "", 0) != -1) {
|
||||
TEST_ERROR("Wrong failure detection 1");
|
||||
goto cleanup;
|
||||
}
|
||||
buf = &bufinit;
|
||||
if (virBufferTrim(buf, NULL, -1) != -1) {
|
||||
TEST_ERROR("Wrong failure detection 2");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
virBufferAddLit(buf, "a;");
|
||||
ACT("", 0, 1);
|
||||
ACT("", -1, 1);
|
||||
ACT(NULL, 1, 1);
|
||||
ACT(NULL, 5, 0);
|
||||
ACT("a", 2, 0);
|
||||
|
||||
virBufferAddLit(buf, ",b,,");
|
||||
ACT("b", -1, 0);
|
||||
ACT("b,,", 1, 1);
|
||||
ACT(",", -1, 1);
|
||||
|
||||
result = virBufferContentAndReset(buf);
|
||||
if (!result || STRNEQ(result, expected)) {
|
||||
virtTestDifference(stderr, expected, result);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
virBufferFreeAndReset(buf);
|
||||
VIR_FREE(result);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
mymain(void)
|
||||
{
|
||||
@ -149,6 +204,7 @@ mymain(void)
|
||||
DO_TEST("EscapeString infinite loop", testBufInfiniteLoop, 1);
|
||||
DO_TEST("VSprintf infinite loop", testBufInfiniteLoop, 0);
|
||||
DO_TEST("Auto-indentation", testBufAutoIndent, 0);
|
||||
DO_TEST("Trim", testBufTrim, 0);
|
||||
|
||||
return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user