[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: [libvirt] [PATCH 06/14] Store parsed query parameters directly in the virURIPtr struct



On 2012年03月21日 01:33, Daniel P. Berrange wrote:
From: "Daniel P. Berrange"<berrange 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()


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]