[libvirt] [PATCH v2 1/6] util: multi-value virTypedParameter

Michal Privoznik mprivozn at redhat.com
Mon May 25 14:59:08 UTC 2015


On 21.05.2015 13:07, Pavel Boldin wrote:
> The `virTypedParamsValidate' function now can be instructed to allow
> multiple entries for some of the keys. For this flag the type with
> the `VIR_TYPED_PARAM_MULTIPLE' flag.
> 
> Add unit tests for this new behaviour.
> 
> Signed-off-by: Pavel Boldin <pboldin at mirantis.com>
> ---
>  src/util/virtypedparam.c  | 108 +++++++++++++++++++-----------
>  src/util/virtypedparam.h  |  10 +++
>  tests/Makefile.am         |   6 ++
>  tests/virtypedparamtest.c | 167 ++++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 252 insertions(+), 39 deletions(-)
>  create mode 100644 tests/virtypedparamtest.c
> 
> diff --git a/src/util/virtypedparam.c b/src/util/virtypedparam.c
> index de2d447..43e49ca 100644
> --- a/src/util/virtypedparam.c
> +++ b/src/util/virtypedparam.c
> @@ -47,11 +47,18 @@ VIR_ENUM_IMPL(virTypedParameter, VIR_TYPED_PARAM_LAST,
>   * internal utility functions (those in libvirt_private.syms) may
>   * report errors that the caller will dispatch.  */
>  
> +static int virTypedParamsSortName(const void *left, const void *right)
> +{
> +    const virTypedParameter *param_left = left, *param_right = right;
> +    return strcmp(param_left->field, param_right->field);
> +}
> +
>  /* Validate that PARAMS contains only recognized parameter names with
> - * correct types, and with no duplicates.  Pass in as many name/type
> - * pairs as appropriate, and pass NULL to end the list of accepted
> - * parameters.  Return 0 on success, -1 on failure with error message
> - * already issued.  */
> + * correct types, and with no duplicates except for parameters
> + * specified with VIR_TYPED_PARAM_MULTIPLE flag in type.
> + * Pass in as many name/type pairs as appropriate, and pass NULL to end
> + * the list of accepted parameters.  Return 0 on success, -1 on failure
> + * with error message already issued.  */
>  int
>  virTypedParamsValidate(virTypedParameterPtr params, int nparams, ...)
>  {
> @@ -60,60 +67,83 @@ virTypedParamsValidate(virTypedParameterPtr params, int nparams, ...)
>      size_t i, j;
>      const char *name;
>      int type;
> +    size_t nkeys = 0, nkeysmax = 0;

s/nkeysmax/nkeysalloc/ because the variable holds count of items allocated.

> +    virTypedParameterPtr sorted = NULL, keys = NULL;
>  
>      va_start(ap, nparams);
>  
> -    /* Yes, this is quadratic, but since we reject duplicates and
> -     * unknowns, it is constrained by the number of var-args passed
> -     * in, which is expected to be small enough to not be
> -     * noticeable.  */
> -    for (i = 0; i < nparams; i++) {
> -        va_end(ap);
> -        va_start(ap, nparams);
> +    if (VIR_ALLOC_N(sorted, nparams) < 0)
> +        goto cleanup;
>  
> -        name = va_arg(ap, const char *);
> -        while (name) {
> -            type = va_arg(ap, int);
> -            if (STREQ(params[i].field, name)) {
> -                if (params[i].type != type) {
> -                    const char *badtype;
> -
> -                    badtype = virTypedParameterTypeToString(params[i].type);
> -                    if (!badtype)
> -                        badtype = virTypedParameterTypeToString(0);
> -                    virReportError(VIR_ERR_INVALID_ARG,
> -                                   _("invalid type '%s' for parameter '%s', "
> -                                     "expected '%s'"),
> -                                   badtype, params[i].field,
> -                                   virTypedParameterTypeToString(type));
> -                }
> -                break;
> -            }
> -            name = va_arg(ap, const char *);
> -        }
> -        if (!name) {
> -            virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
> -                           _("parameter '%s' not supported"),
> -                           params[i].field);
> +    /* Here we intentionally don't copy values */
> +    memcpy(sorted, params, sizeof(*params) * nparams);
> +    qsort(sorted, nparams, sizeof(*sorted), virTypedParamsSortName);
> +
> +    name = va_arg(ap, const char *);
> +    while (name) {
> +        type = va_arg(ap, int);
> +        if (VIR_RESIZE_N(keys, nkeysmax, nkeys, 1) < 0)
> +            goto cleanup;
> +
> +        if (virStrcpyStatic(keys[nkeys].field, name) == NULL) {
> +            virReportError(VIR_ERR_INTERNAL_ERROR,
> +                           _("Field name '%s' too long"), name);
>              goto cleanup;
>          }
> -        for (j = 0; j < i; j++) {
> -            if (STREQ(params[i].field, params[j].field)) {
> +
> +        keys[nkeys].type = type & ~VIR_TYPED_PARAM_MULTIPLE;
> +        /* Value is not used anyway */
> +        keys[nkeys].value.i = type & VIR_TYPED_PARAM_MULTIPLE;
> +
> +        nkeys++;
> +        name = va_arg(ap, const char *);
> +    }
> +
> +    qsort(keys, nkeys, sizeof(*keys), virTypedParamsSortName);
> +
> +    for (i = 0, j = 0; i < nparams && j < nkeys;) {
> +        if (STRNEQ(sorted[i].field, keys[j].field)) {
> +            j++;
> +        } else {
> +            if (i > j && !(keys[j].value.i & VIR_TYPED_PARAM_MULTIPLE)) {
>                  virReportError(VIR_ERR_INVALID_ARG,
>                                 _("parameter '%s' occurs multiple times"),
> -                               params[i].field);
> +                               sorted[i].field);
> +                goto cleanup;
> +            }
> +            if (sorted[i].type != keys[j].type) {
> +                const char *badtype;
> +
> +                badtype = virTypedParameterTypeToString(sorted[i].type);
> +                if (!badtype)
> +                    badtype = virTypedParameterTypeToString(0);
> +                virReportError(VIR_ERR_INVALID_ARG,
> +                               _("invalid type '%s' for parameter '%s', "
> +                                 "expected '%s'"),
> +                               badtype, sorted[i].field,
> +                               virTypedParameterTypeToString(keys[j].type));
>                  goto cleanup;
>              }
> +            i++;
>          }
>      }
>  
> +    if (j == nkeys && i != nparams) {
> +        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
> +                       _("parameter '%s' not supported"),
> +                       sorted[i].field);
> +        goto cleanup;
> +    }
> +
>      ret = 0;
>   cleanup:
>      va_end(ap);
> +    VIR_FREE(sorted);
> +    VIR_FREE(keys);
>      return ret;
> -
>  }
>  


ACK

Michal




More information about the libvir-list mailing list