return strcmp(param_left->field, param_right->field);
}
+static int
+virTypedParamsSortTemplate(const void *left,
+ const void *right,
+ void *opaque G_GNUC_UNUSED)
+{
+ const virTypedParamValidationTemplate *param_left = left;
+ const virTypedParamValidationTemplate *param_right = right;
+ return strcmp(param_left->name, param_right->name);
+}
+
/* Validate that PARAMS contains only recognized parameter names with
* 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, ...)
+static int
+virTypedParamsValidateInternal(virTypedParameterPtr params,
+ size_t nparams,
+ virTypedParamValidationTemplate *templates,
+ size_t ntemplates)
{
- va_list ap;
size_t i;
size_t j;
- const char *name;
const char *last_name = NULL;
- size_t nkeys = 0;
- size_t nkeysalloc = 0;
- g_autofree virTypedParameterPtr sorted = NULL;
- g_autofree virTypedParameterPtr keys = NULL;
+ g_autofree virTypedParameterPtr sorted = g_new0(virTypedParameter, nparams);
- if (!nparams) {
- return 0;
- }
-
- va_start(ap, nparams);
-
- sorted = g_new0(virTypedParameter, nparams);
-
- /* Here we intentionally don't copy values */
memcpy(sorted, params, sizeof(*params) * nparams);
g_qsort_with_data(sorted, nparams,
sizeof(*sorted), virTypedParamsSortName, NULL);
- name = va_arg(ap, const char *);
- while (name) {
- int type = va_arg(ap, int);
- VIR_RESIZE_N(keys, nkeysalloc, nkeys, 1);
-
- if (virStrcpyStatic(keys[nkeys].field, name) < 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Field name '%1$s' too long"), name);
- va_end(ap);
- return -1;
- }
-
- 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 *);
- }
-
- va_end(ap);
-
- g_qsort_with_data(keys, nkeys, sizeof(*keys), virTypedParamsSortName, NULL);
+ g_qsort_with_data(templates, ntemplates,
+ sizeof(*templates), virTypedParamsSortTemplate, NULL);
- for (i = 0, j = 0; i < nparams && j < nkeys;) {
- if (STRNEQ(sorted[i].field, keys[j].field)) {
+ for (i = 0, j = 0; i < nparams && j < ntemplates;) {
+ if (STRNEQ(sorted[i].field, templates[j].name)) {
j++;
} else {
- if (STREQ_NULLABLE(last_name, sorted[i].field) &&
- !(keys[j].value.i & VIR_TYPED_PARAM_MULTIPLE)) {
+ unsigned int expected_type = templates[j].typeflags & ~VIR_TYPED_PARAM_MULTIPLE;
+ bool multiple = templates[j].typeflags & VIR_TYPED_PARAM_MULTIPLE;
+
+ if (STREQ_NULLABLE(last_name, sorted[i].field) && !multiple) {
virReportError(VIR_ERR_INVALID_ARG,
_("parameter '%1$s' occurs multiple times"),
sorted[i].field);
return -1;
}
- if (virTypedParamValidateType(sorted + i, keys[j].type) < 0)
+ if (virTypedParamValidateType(sorted + i, expected_type) < 0)
return -1;
last_name = sorted[i].field;
}
}
- if (j == nkeys && i != nparams) {
+ if (j == ntemplates && i != nparams) {
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
_("parameter '%1$s' not supported"),
sorted[i].field);
}
+/* Validate that PARAMS contains only recognized parameter names with
+ * 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,
+ ...)
+{
+ va_list ap;
+ const char *name;
+ g_autofree virTypedParamValidationTemplate *templates = NULL;
+ size_t ntemplates = 0;
+ size_t ntemplatesalloc = 0;
+
+ if (nparams == 0)
+ return 0;
+
+ va_start(ap, nparams);
+
+ for (name = va_arg(ap, const char *); name; name = va_arg(ap, const char *)) {
+ VIR_RESIZE_N(templates, ntemplatesalloc, ntemplates, 1);
+
+ if (virStrcpy((char *)templates[ntemplates].name, name, VIR_TYPED_PARAM_FIELD_LENGTH) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Field name '%1$s' too long"), name);
+ va_end(ap);
+ return -1;
+ }
+
+ templates[ntemplates].typeflags = va_arg(ap, unsigned int);
+ ntemplates++;
+ }
+
+ va_end(ap);
+
+ return virTypedParamsValidateInternal(params, nparams, templates, ntemplates);
+}
+
+
+int
+virTypedParamsValidateTemplate(virTypedParameterPtr params,
+ int nparams,
+ const virTypedParamValidationTemplate *templates)
+{
+ size_t ntemplates = 0;
+ g_autofree virTypedParamValidationTemplate *templ_copy = NULL;
+
+ /* we need to copy the list of templates because
+ * 'virTypedParamsValidateInternal' will need to sort it */
+ while (*templates[ntemplates++].name == '\0')
+ ;
+
+ templ_copy = g_new0(virTypedParamValidationTemplate, ntemplates);
+ memcpy(templ_copy, templates, sizeof(*templates) * ntemplates);
+
+ return virTypedParamsValidateInternal(params, nparams, templ_copy, ntemplates);
+}
+
+
/* Check if params contains only specified parameter names. Return true if
* only specified names are present in params, false if params contains any
* unspecified parameter name. */