Re: [libvirt] [PATCH v2 3/6] util: virTypedParams{Filter, PickStrings}

2015-05-25 Thread Michal Privoznik
On 21.05.2015 13:07, Pavel Boldin wrote:
> Add multikey API:
> 
>  * virTypedParamsFilter that returns all the parameters with specified name.
>  * virTypedParamsPickStrings that returns a NULL-terminated `const char**'
>list with all the values for specified name and string type.
> 
> Signed-off-by: Pavel Boldin 
> ---
>  include/libvirt/libvirt-host.h |  10 
>  src/libvirt_public.syms|   6 +++
>  src/util/virtypedparam.c   | 107 
> +
>  tests/virtypedparamtest.c  |  96 
>  4 files changed, 219 insertions(+)
> 
> diff --git a/include/libvirt/libvirt-host.h b/include/libvirt/libvirt-host.h
> index 070550b..36267fc 100644
> --- a/include/libvirt/libvirt-host.h
> +++ b/include/libvirt/libvirt-host.h
> @@ -249,6 +249,11 @@ virTypedParamsGet   (virTypedParameterPtr params,
>   int nparams,
>   const char *name);
>  int
> +virTypedParamsFilter(virTypedParameterPtr params,
> + int nparams,
> + const char *name,
> + virTypedParameterPtr **ret);
> +int
>  virTypedParamsGetInt(virTypedParameterPtr params,
>   int nparams,
>   const char *name,
> @@ -283,6 +288,11 @@ virTypedParamsGetString (virTypedParameterPtr params,
>   int nparams,
>   const char *name,
>   const char **value);
> +const char **
> +virTypedParamsPickStrings(virTypedParameterPtr params,
> + int nparams,
> + const char *name,
> + size_t *picked);
>  int
>  virTypedParamsAddInt(virTypedParameterPtr *params,
>   int *nparams,
> diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
> index ef3d2f0..8fc8c42 100644
> --- a/src/libvirt_public.syms
> +++ b/src/libvirt_public.syms
> @@ -710,4 +710,10 @@ LIBVIRT_1.2.15 {
>  virDomainDelIOThread;
>  } LIBVIRT_1.2.14;
>  
> +LIBVIRT_1.2.16 {
> +global:
> +virTypedParamsFilter;
> +virTypedParamsPickStrings;
> +} LIBVIRT_1.2.15;
> +
>  #  define new API here using predicted next version number 
> diff --git a/src/util/virtypedparam.c b/src/util/virtypedparam.c
> index ec20b74..a3d959e 100644
> --- a/src/util/virtypedparam.c
> +++ b/src/util/virtypedparam.c
> @@ -481,6 +481,58 @@ virTypedParamsGet(virTypedParameterPtr params,
>  }
>  
>  
> +/**
> + * virTypedParamsFilter:
> + * @params: array of typed parameters
> + * @nparams: number of parameters in the @params array
> + * @name: name of the parameter to find
> + * @ret: pointer to the returned array
> + *
> + *
> + * Filters @params retaining only the parameters named @name in the
> + * resulting array @ret. Caller should free the @ret array but no the

s/no/not/

> + * items since they are pointing to the @params elements.
> + *
> + * Returns amount of elements in @ret on success, -1 on error.
> + */
> +int
> +virTypedParamsFilter(virTypedParameterPtr params,
> + int nparams,
> + const char *name,
> + virTypedParameterPtr **ret)
> +{
> +size_t i, max = 0, n = 0;

s/max/alloc/

> +
> +virResetLastError();
> +
> +if (!params || !name || !ret) {
> +virReportError(VIR_ERR_INVALID_ARG,
> +   _("Required argument is missing: %s"),
> +   !params ? "params" : !name ? "name" : "ret");
> +goto error;

We have a macro for that: virCheckNonNullArgGoto()

> +}
> +
> +for (i = 0; i < nparams; i++) {
> +if (STREQ(params[i].field, name)) {
> +if (VIR_RESIZE_N(*ret, max, n, 1) < 0)
> +goto error;
> +
> +(*ret)[n] = ¶ms[i];
> +
> +n++;
> +}
> +}

So if there's no match, @ret is untouched. This is not cool, consider
the following code:

virTypedParameterPtr *ret;
if (virTypedParamsFilter(.., &ret) < 0) {
  error;
} else {
  success;
  free(ret);
}

The free() may end up freeing a random pointer.

> +
> +return n;
> +
> + error:
> +if (ret)
> +VIR_FREE(*ret);
> +virDispatchError(NULL);
> +return -1;
> +}
> +
> +
>  #define VIR_TYPED_PARAM_CHECK_TYPE(check_type)  \
>  do { if (param->type != check_type) {   \
>  virReportError(VIR_ERR_INVALID_ARG, \
> @@ -749,6 +801,61 @@ virTypedParamsGetString(virTypedParameterPtr params,
>  
>  
>  /**
> + * virTypedParamsPickStrings:
> + * @params: array of typed parameters
> + * @nparams: number of parameters in the @params array
> + * @name: name of the parameter to find
> + * @picked: pointer to the amount of picked strings.
> + *
> + *
> + * Finds typed parameters called @name.
> + *
> + * Returns a string list, which 

[libvirt] [PATCH v2 3/6] util: virTypedParams{Filter,PickStrings}

2015-05-21 Thread Pavel Boldin
Add multikey API:

 * virTypedParamsFilter that returns all the parameters with specified name.
 * virTypedParamsPickStrings that returns a NULL-terminated `const char**'
   list with all the values for specified name and string type.

Signed-off-by: Pavel Boldin 
---
 include/libvirt/libvirt-host.h |  10 
 src/libvirt_public.syms|   6 +++
 src/util/virtypedparam.c   | 107 +
 tests/virtypedparamtest.c  |  96 
 4 files changed, 219 insertions(+)

diff --git a/include/libvirt/libvirt-host.h b/include/libvirt/libvirt-host.h
index 070550b..36267fc 100644
--- a/include/libvirt/libvirt-host.h
+++ b/include/libvirt/libvirt-host.h
@@ -249,6 +249,11 @@ virTypedParamsGet   (virTypedParameterPtr params,
  int nparams,
  const char *name);
 int
+virTypedParamsFilter(virTypedParameterPtr params,
+ int nparams,
+ const char *name,
+ virTypedParameterPtr **ret);
+int
 virTypedParamsGetInt(virTypedParameterPtr params,
  int nparams,
  const char *name,
@@ -283,6 +288,11 @@ virTypedParamsGetString (virTypedParameterPtr params,
  int nparams,
  const char *name,
  const char **value);
+const char **
+virTypedParamsPickStrings(virTypedParameterPtr params,
+ int nparams,
+ const char *name,
+ size_t *picked);
 int
 virTypedParamsAddInt(virTypedParameterPtr *params,
  int *nparams,
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index ef3d2f0..8fc8c42 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -710,4 +710,10 @@ LIBVIRT_1.2.15 {
 virDomainDelIOThread;
 } LIBVIRT_1.2.14;
 
+LIBVIRT_1.2.16 {
+global:
+virTypedParamsFilter;
+virTypedParamsPickStrings;
+} LIBVIRT_1.2.15;
+
 #  define new API here using predicted next version number 
diff --git a/src/util/virtypedparam.c b/src/util/virtypedparam.c
index ec20b74..a3d959e 100644
--- a/src/util/virtypedparam.c
+++ b/src/util/virtypedparam.c
@@ -481,6 +481,58 @@ virTypedParamsGet(virTypedParameterPtr params,
 }
 
 
+/**
+ * virTypedParamsFilter:
+ * @params: array of typed parameters
+ * @nparams: number of parameters in the @params array
+ * @name: name of the parameter to find
+ * @ret: pointer to the returned array
+ *
+ *
+ * Filters @params retaining only the parameters named @name in the
+ * resulting array @ret. Caller should free the @ret array but no the
+ * items since they are pointing to the @params elements.
+ *
+ * Returns amount of elements in @ret on success, -1 on error.
+ */
+int
+virTypedParamsFilter(virTypedParameterPtr params,
+ int nparams,
+ const char *name,
+ virTypedParameterPtr **ret)
+{
+size_t i, max = 0, n = 0;
+
+virResetLastError();
+
+if (!params || !name || !ret) {
+virReportError(VIR_ERR_INVALID_ARG,
+   _("Required argument is missing: %s"),
+   !params ? "params" : !name ? "name" : "ret");
+goto error;
+}
+
+for (i = 0; i < nparams; i++) {
+if (STREQ(params[i].field, name)) {
+if (VIR_RESIZE_N(*ret, max, n, 1) < 0)
+goto error;
+
+(*ret)[n] = ¶ms[i];
+
+n++;
+}
+}
+
+return n;
+
+ error:
+if (ret)
+VIR_FREE(*ret);
+virDispatchError(NULL);
+return -1;
+}
+
+
 #define VIR_TYPED_PARAM_CHECK_TYPE(check_type)  \
 do { if (param->type != check_type) {   \
 virReportError(VIR_ERR_INVALID_ARG, \
@@ -749,6 +801,61 @@ virTypedParamsGetString(virTypedParameterPtr params,
 
 
 /**
+ * virTypedParamsPickStrings:
+ * @params: array of typed parameters
+ * @nparams: number of parameters in the @params array
+ * @name: name of the parameter to find
+ * @picked: pointer to the amount of picked strings.
+ *
+ *
+ * Finds typed parameters called @name.
+ *
+ * Returns a string list, which is a NULL terminated array of pointers to
+ * strings. Since a NULL is a valid parameter string value caller can ask
+ * for exact amount of picked strings using @picked argument.
+ *
+ * Caller should free the returned array but not the items since they are
+ * taken from @params array.
+ */
+const char **
+virTypedParamsPickStrings(virTypedParameterPtr params,
+  int nparams, const char *name,
+  size_t *picked)
+{
+const char **values = NULL;
+size_t i, n;
+int nfiltered;
+virTypedParameterPtr *filtered = NULL;
+
+virResetLastError();
+
+nfiltered = virTypedParamsFi