+Wed May 10 13:17:00 CEST 2006 Karel Zak <kzak@redhat.com>
+
+ * 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 <kzak@redhat.com>
* tests/Makefile.am tests/xmlrpctest.c tests/testutils.h: added test
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);
}
}
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
/*
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
virBufferVSprintf(buf, "%*s<value>", indent, "");
switch (value->kind) {
case XML_RPC_ARRAY:
- virBufferVSprintf(buf, "<array><data>\n", indent, "");
+ virBufferStrcat(buf, "<array><data>\n", NULL);
for (i = 0; i < value->value.array.n_elements; i++)
xmlRpcValueMarshal(value->value.array.elements[i], buf, indent+2);
virBufferVSprintf(buf, "%*s</data></array>", indent, "");
break;
case XML_RPC_STRUCT:
- virBufferVSprintf(buf, "<struct>\n", indent, "");
+ virBufferStrcat(buf, "<struct>\n", NULL);
indent += 2;
for (elem = value->value.dict.root; elem; elem = elem->next) {
virBufferVSprintf(buf, "%*s<member>\n", indent, "");
TODO;
break;
case XML_RPC_STRING:
- virBufferVSprintf(buf, "<string>%s</string>", value->value.string);
+ virBufferStrcat(buf,
+ "<string>", value->value.string, "</string>", NULL);
break;
case XML_RPC_NIL:
- virBufferVSprintf(buf, "<nil> </nil>");
+ virBufferStrcat(buf, "<nil> </nil>", NULL);
break;
}
- virBufferVSprintf(buf, "</value>\n");
+ virBufferStrcat(buf, "</value>\n", NULL);
}
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,
- "<?xml version=\"1.0\"?>\n"
- "<methodCall>\n"
- " <methodName>%s</methodName>\n"
- " <params>\n",
- request);
+ buf = virBufferNew(1024);
+
+ virBufferStrcat(buf,
+ "<?xml version=\"1.0\"?>\n"
+ "<methodCall>\n"
+ " <methodName>", request, "</methodName>\n"
+ " <params>\n", NULL);
for (i = 0; i < argc; i++) {
- virBufferVSprintf(buf,
- " <param>\n");
+ virBufferStrcat(buf,
+ " <param>\n", NULL);
xmlRpcValueMarshal(argv[i], buf, 6);
- virBufferVSprintf(buf,
- " </param>\n");
+ virBufferStrcat(buf,
+ " </param>\n", NULL);
}
- virBufferVSprintf(buf,
- " </params>\n"
- "</methodCall>\n");
-
+ virBufferStrcat(buf,
+ " </params>\n"
+ "</methodCall>\n", NULL);
return buf;
}
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;
}
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)
{
}
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;
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;
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);
}