From 0d8e15fa754bf082f3120a10a1fdd7e34b6989c6 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Wed, 10 May 2006 12:15:49 +0000 Subject: [PATCH] added virBufferStrcat --- ChangeLog | 7 ++++++ src/xml.c | 61 +++++++++++++++++++++++++++++++++++++++++++--- src/xml.h | 2 ++ src/xmlrpc.c | 44 +++++++++++++++------------------ tests/xmlrpctest.c | 51 ++++++++++++++++++++++++++++++++------ 5 files changed, 129 insertions(+), 36 deletions(-) diff --git a/ChangeLog b/ChangeLog index 930705e277..41dc9902ac 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +Wed May 10 13:17:00 CEST 2006 Karel Zak + + * src/xml.c src/xml.h: added virBufferNew() and virBufferStrcat() + * tests/xmlrpctest.c: added performace tests for virBufferStrcat() and + virBufferVSprintf() + * src/xmlrpc.c: used virBufferStrcat() + Tue May 9 16:37:22 CEST 2006 Karel Zak * tests/Makefile.am tests/xmlrpctest.c tests/testutils.h: added test diff --git a/src/xml.c b/src/xml.c index b273154be0..f46978bb4f 100644 --- a/src/xml.c +++ b/src/xml.c @@ -107,20 +107,40 @@ virBufferAdd(virBufferPtr buf, const char *str, int len) return (-1); } } - + /* XXX: memmove() is 2x slower than memcpy(), do we really need it? */ memmove(&buf->content[buf->use], str, len); buf->use += len; buf->content[buf->use] = 0; return (0); } +virBufferPtr +virBufferNew(unsigned int size) +{ + virBufferPtr buf; + + if (!(buf = malloc(sizeof(*buf)))) { + virXMLError(VIR_ERR_NO_MEMORY, "allocate new buffer", sizeof(*buf)); + return NULL; + } + if (size && (buf->content = malloc(size))==NULL) { + virXMLError(VIR_ERR_NO_MEMORY, "allocate buffer content", size); + free(buf); + return NULL; + } + buf->size = size; + buf->use = 0; + + return buf; +} + void virBufferFree(virBufferPtr buf) { if (buf) { - if (buf->content) - free(buf->content); - free(buf); + if (buf->content) + free(buf->content); + free(buf); } } @@ -162,6 +182,39 @@ virBufferVSprintf(virBufferPtr buf, const char *format, ...) return (0); } +/** + * virBufferStrcat: + * @buf: the buffer to dump + * @argptr: the variable list of strings, the last argument must be NULL + * + * Concatenate strings to an XML buffer. + * + * Returns 0 successful, -1 in case of internal or API error. + */ +int +virBufferStrcat(virBufferPtr buf, ...) +{ + va_list ap; + char *str; + + 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)) + return -1; + } + memcpy(&buf->content[buf->use], str, len); + buf->use += len; + buf->content[buf->use] = 0; + } + va_end(ap); + return 0; +} + #if 0 /* diff --git a/src/xml.h b/src/xml.h index 7121b55d4f..fbd5895ea4 100644 --- a/src/xml.h +++ b/src/xml.h @@ -24,9 +24,11 @@ struct _virBuffer { unsigned int size; /* The buffer size */ }; +virBufferPtr virBufferNew(unsigned int size); void virBufferFree(virBufferPtr buf); int virBufferAdd(virBufferPtr buf, const char *str, int len); int virBufferVSprintf(virBufferPtr buf, const char *format, ...); +int virBufferStrcat(virBufferPtr buf, ...); char *virDomainParseXMLDesc(const char *xmldesc, char **name); #ifdef __cplusplus diff --git a/src/xmlrpc.c b/src/xmlrpc.c index eceb2872c6..2b6db87af7 100644 --- a/src/xmlrpc.c +++ b/src/xmlrpc.c @@ -266,13 +266,13 @@ void xmlRpcValueMarshal(xmlRpcValuePtr value, virBufferPtr buf, int indent) virBufferVSprintf(buf, "%*s", indent, ""); switch (value->kind) { case XML_RPC_ARRAY: - virBufferVSprintf(buf, "\n", indent, ""); + virBufferStrcat(buf, "\n", NULL); for (i = 0; i < value->value.array.n_elements; i++) xmlRpcValueMarshal(value->value.array.elements[i], buf, indent+2); virBufferVSprintf(buf, "%*s", indent, ""); break; case XML_RPC_STRUCT: - virBufferVSprintf(buf, "\n", indent, ""); + virBufferStrcat(buf, "\n", NULL); indent += 2; for (elem = value->value.dict.root; elem; elem = elem->next) { virBufferVSprintf(buf, "%*s\n", indent, ""); @@ -306,13 +306,14 @@ void xmlRpcValueMarshal(xmlRpcValuePtr value, virBufferPtr buf, int indent) TODO; break; case XML_RPC_STRING: - virBufferVSprintf(buf, "%s", value->value.string); + virBufferStrcat(buf, + "", value->value.string, "", NULL); break; case XML_RPC_NIL: - virBufferVSprintf(buf, " "); + virBufferStrcat(buf, " ", NULL); break; } - virBufferVSprintf(buf, "\n"); + virBufferStrcat(buf, "\n", NULL); } virBufferPtr xmlRpcMarshalRequest(const char *request, @@ -321,28 +322,23 @@ virBufferPtr xmlRpcMarshalRequest(const char *request, virBufferPtr buf; int i; - buf = malloc(sizeof(*buf)); - buf->size = 1024; - buf->content = malloc(buf->size); - buf->use = 0; - - virBufferVSprintf(buf, - "\n" - "\n" - " %s\n" - " \n", - request); + buf = virBufferNew(1024); + + virBufferStrcat(buf, + "\n" + "\n" + " ", request, "\n" + " \n", NULL); for (i = 0; i < argc; i++) { - virBufferVSprintf(buf, - " \n"); + virBufferStrcat(buf, + " \n", NULL); xmlRpcValueMarshal(argv[i], buf, 6); - virBufferVSprintf(buf, - " \n"); + virBufferStrcat(buf, + " \n", NULL); } - virBufferVSprintf(buf, - " \n" - "\n"); - + virBufferStrcat(buf, + " \n" + "\n", NULL); return buf; } diff --git a/tests/xmlrpctest.c b/tests/xmlrpctest.c index 02f0fa4978..9540bffaf9 100644 --- a/tests/xmlrpctest.c +++ b/tests/xmlrpctest.c @@ -151,11 +151,10 @@ testMarshalRequestSTRING(void *data ATTRIBUTE_UNUSED) int check = data ? *((int *)data) : 0; virBufferPtr buf = marshalRequest("s", str); - if (check) + if (check) ret = checkRequestValue(buf->content, "string(/methodCall/params/param[1]/value/string)", XML_RPC_STRING, (void *) str); - virBufferFree(buf); return ret; } @@ -177,6 +176,32 @@ testMarshalRequestDOUBLE(void *data) return ret; } +static int +testBufferStrcat(void *data ATTRIBUTE_UNUSED) +{ + virBufferPtr buf = virBufferNew(1000*32); /* don't waste time with realloc */ + int i; + + for (i=0; i < 1000; i++) + virBufferStrcat(buf, "My name is ", "libvirt", ".\n", NULL); + + virBufferFree(buf); + return 0; +} + +static int +testBufferVSprintf(void *data ATTRIBUTE_UNUSED) +{ + virBufferPtr buf = virBufferNew(1000*32); /* don't waste time with realloc */ + int i; + + for (i=0; i < 1000; i++) + virBufferVSprintf(buf, "My name is %s.\n", "libvirt"); + + virBufferFree(buf); + return 0; +} + int main(int argc, char **argv) { @@ -194,15 +219,17 @@ main(int argc, char **argv) } if (argc == 2) url = argv[1]; - + + /* + * client-server tests + */ if (!(cxt = xmlRpcContextNew(url))) { fprintf(stderr, "%s: failed create new RPC context\n", progname); exit(EXIT_FAILURE); } - /* client-server tests */ - if (virtTestRun("XML-RPC methodCall INT+INT", + if (virtTestRun("XML-RPC methodCall INT+INT", NLOOPS, testMethodPlusINT, (void *) cxt) != 0) ret = -1; @@ -210,7 +237,11 @@ main(int argc, char **argv) NLOOPS, testMethodPlusDOUBLE, (void *) cxt) != 0) ret = -1; - /* regression / performance tests */ + xmlRpcContextFree(cxt); + + /* + * regression / performance tests + */ if (virtTestRun("XML-RPC request marshalling: INT (check)", 1, testMarshalRequestINT, (void *) &check) != 0) ret = -1; @@ -231,8 +262,12 @@ main(int argc, char **argv) if (virtTestRun("XML-RPC request marshalling: STRING", NLOOPS, testMarshalRequestSTRING, NULL) != 0) ret = -1; - - xmlRpcContextFree(cxt); + + if (virtTestRun("Buffer: strcat", NLOOPS, testBufferStrcat, NULL) != 0) + ret = -1; + if (virtTestRun("Buffer: sprintf", NLOOPS, testBufferVSprintf, NULL) != 0) + ret = -1; + exit(ret==0 ? EXIT_SUCCESS : EXIT_FAILURE); } -- 2.39.5