[libvirt] [PATCH 06/14] Store parsed query parameters directly in the virURIPtr struct
Osier Yang
jyang at redhat.com
Thu Mar 22 07:42:17 UTC 2012
On 2012年03月21日 01:33, Daniel P. Berrange wrote:
> From: "Daniel P. Berrange"<berrange at redhat.com>
>
> Avoid the need for each driver to parse query parameters itself
> by storing them directly in the virURIPtr struct. The parsing
> code is a copy of that from src/util/qparams.c The latter will
> be removed in a later patch
>
> * src/util/viruri.h: Add query params to virURIPtr
> * src/util/viruri.c: Parse query parameters when creating virURIPtr
> * tests/viruritest.c: Expand test to cover params
> ---
> src/libvirt_private.syms | 1 +
> src/util/viruri.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++
> src/util/viruri.h | 15 +++++
> tests/viruritest.c | 46 +++++++++++++---
> 4 files changed, 193 insertions(+), 8 deletions(-)
>
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index 7cd6a96..49fb2ee 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -1471,6 +1471,7 @@ virTypedParameterAssign;
> # viruri.h
> virURIFree;
> virURIFormat;
> +virURIFormatQuery;
> virURIParse;
>
>
> diff --git a/src/util/viruri.c b/src/util/viruri.c
> index d8618d1..f5adca5 100644
> --- a/src/util/viruri.c
> +++ b/src/util/viruri.c
> @@ -13,6 +13,7 @@
> #include "memory.h"
> #include "util.h"
> #include "virterror_internal.h"
> +#include "buf.h"
>
> #define VIR_FROM_THIS VIR_FROM_URI
>
> @@ -21,6 +22,117 @@
> __FUNCTION__, __LINE__, __VA_ARGS__)
>
>
> +static int
> +virURIParamAppend(virURIPtr uri,
> + const char *name,
> + const char *value)
> +{
> + char *pname = NULL;
> + char *pvalue = NULL;
> +
> + if (!(pname = strdup(name)))
> + goto no_memory;
> + if (!(pvalue = strdup (value)))
> + goto no_memory;
> +
> + if (VIR_RESIZE_N(uri->params, uri->paramsAlloc, uri->paramsCount, 1)< 0)
> + goto no_memory;
> +
> + uri->params[uri->paramsCount].name = pname;
> + uri->params[uri->paramsCount].value = pvalue;
> + uri->params[uri->paramsCount].ignore = 0;
> + uri->paramsCount++;
> +
> + return 0;
> +
> +no_memory:
> + VIR_FREE(pname);
> + VIR_FREE(pvalue);
> + virReportOOMError();
> + return -1;
> +}
> +
> +
> +static int
> +virURIParseParams(virURIPtr uri)
> +{
> + const char *end, *eq;
> + const char *query = uri->query;
> +
> + if (!query || query[0] == '\0')
> + return 0;
> +
> + while (*query) {
> + char *name = NULL, *value = NULL;
> +
> + /* Find the next separator, or end of the string. */
> + end = strchr (query, '&');
> + if (!end)
> + end = strchr (query, ';');
> + if (!end)
> + end = query + strlen (query);
> +
> + /* Find the first '=' character between here and end. */
> + eq = strchr (query, '=');
> + if (eq&& eq>= end) eq = NULL;
> +
> + /* Empty section (eg. "&&"). */
> + if (end == query)
> + goto next;
> +
> + /* If there is no '=' character, then we have just "name"
> + * and consistent with CGI.pm we assume value is "".
> + */
> + else if (!eq) {
> + name = xmlURIUnescapeString (query, end - query, NULL);
> + if (!name) goto no_memory;
> + }
> + /* Or if we have "name=" here (works around annoying
> + * problem when calling xmlURIUnescapeString with len = 0).
> + */
> + else if (eq+1 == end) {
> + name = xmlURIUnescapeString (query, eq - query, NULL);
> + if (!name) goto no_memory;
> + }
> + /* If the '=' character is at the beginning then we have
> + * "=value" and consistent with CGI.pm we _ignore_ this.
> + */
> + else if (query == eq)
> + goto next;
> +
> + /* Otherwise it's "name=value". */
> + else {
> + name = xmlURIUnescapeString (query, eq - query, NULL);
> + if (!name)
> + goto no_memory;
> + value = xmlURIUnescapeString (eq+1, end - (eq+1), NULL);
> + if (!value) {
> + VIR_FREE(name);
> + goto no_memory;
> + }
> + }
> +
> + /* Append to the parameter set. */
> + if (virURIParamAppend(uri, name, value ? value : "")< 0) {
> + VIR_FREE(name);
> + VIR_FREE(value);
> + goto no_memory;
> + }
> + VIR_FREE(name);
> + VIR_FREE(value);
> +
> + next:
> + query = end;
> + if (*query) query ++; /* skip '&' separator */
> + }
> +
> + return 0;
> +
> + no_memory:
> + virReportOOMError();
> + return -1;
> +}
> +
> /**
> * virURIParse:
> * @uri: URI to parse
> @@ -92,12 +204,16 @@ virURIParse(const char *uri)
> * the uri with xmlFreeURI() */
> }
>
> + if (virURIParseParams(ret)< 0)
> + goto error;
> +
> xmlFreeURI(xmluri);
>
> return ret;
>
> no_memory:
> virReportOOMError();
> +error:
> xmlFreeURI(xmluri);
> virURIFree(ret);
> return NULL;
> @@ -153,6 +269,29 @@ cleanup:
> }
>
>
> +char *virURIFormatQuery(virURIPtr uri)
> +{
> + virBuffer buf = VIR_BUFFER_INITIALIZER;
> + int i, amp = 0;
> +
> + for (i = 0; i< uri->paramsCount; ++i) {
> + if (!uri->params[i].ignore) {
> + if (amp) virBufferAddChar (&buf, '&');
> + virBufferStrcat (&buf, uri->params[i].name, "=", NULL);
> + virBufferURIEncodeString (&buf, uri->params[i].value);
> + amp = 1;
> + }
> + }
> +
> + if (virBufferError(&buf)) {
> + virBufferFreeAndReset(&buf);
> + virReportOOMError();
> + return NULL;
> + }
> +
> + return virBufferContentAndReset(&buf);
> +}
> +
> /**
> * virURIFree:
> * @uri: uri to free
> diff --git a/src/util/viruri.h b/src/util/viruri.h
> index dd270de..6fe0b2e 100644
> --- a/src/util/viruri.h
> +++ b/src/util/viruri.h
> @@ -16,6 +16,15 @@
> typedef struct _virURI virURI;
> typedef virURI *virURIPtr;
>
> +typedef struct _virURIParam virURIParam;
> +typedef virURIParam *virURIParamPtr;
> +
> +struct _virURIParam {
> + char *name; /* Name (unescaped). */
> + char *value; /* Value (unescaped). */
> + bool ignore; /* Ignore this field in qparam_get_query */
> +};
> +
> struct _virURI {
> char *scheme; /* the URI scheme */
> char *server; /* the server part */
> @@ -24,6 +33,10 @@ struct _virURI {
> char *path; /* the path string */
> char *query; /* the query string */
> char *fragment; /* the fragment string */
> +
> + size_t paramsCount;
> + size_t paramsAlloc;
> + virURIParamPtr params;
> };
>
> virURIPtr virURIParse(const char *uri)
> @@ -31,6 +44,8 @@ virURIPtr virURIParse(const char *uri)
> char *virURIFormat(virURIPtr uri)
> ATTRIBUTE_NONNULL(1);
>
> +char *virURIFormatQuery(virURIPtr uri);
> +
> void virURIFree(virURIPtr uri);
Oh, the params array is not free()'ed in virURIFree()
More information about the libvir-list
mailing list