[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