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 <pboldin@xxxxxxxxxxxx> --- 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 = virTypedParamsFilter(params, nparams, name, &filtered); + + if (nfiltered <= 0) + return NULL; + + if (VIR_ALLOC_N(values, nfiltered + 1) < 0) + goto error; + + for (n = 0, i = 0; i < nfiltered; i++) { + if (filtered[i]->type == VIR_TYPED_PARAM_STRING) + values[n++] = filtered[i]->value.s; + } + + if (picked) + *picked = n; + + VIR_FREE(filtered); + return values; + + error: + VIR_FREE(filtered); + virDispatchError(NULL); + return NULL; +} + + +/** * virTypedParamsAddInt: * @params: pointer to the array of typed parameters * @nparams: number of parameters in the @params array diff --git a/tests/virtypedparamtest.c b/tests/virtypedparamtest.c index 95e22a7..945dbe7 100644 --- a/tests/virtypedparamtest.c +++ b/tests/virtypedparamtest.c @@ -81,6 +81,96 @@ testTypedParamsValidate(const void *opaque) .nparams = PARAMS_SIZE(__VA_ARGS__), static int +testTypedParamsFilter(const void *opaque ATTRIBUTE_UNUSED) +{ + size_t i, nfiltered; + int rv = -1; + virTypedParameter params[] = { + { .field = "bar", .type = VIR_TYPED_PARAM_UINT }, + { .field = "foo", .type = VIR_TYPED_PARAM_INT }, + { .field = "bar", .type = VIR_TYPED_PARAM_UINT }, + { .field = "foo", .type = VIR_TYPED_PARAM_INT }, + { .field = "foobar", .type = VIR_TYPED_PARAM_STRING }, + { .field = "foo", .type = VIR_TYPED_PARAM_INT } + }; + virTypedParameterPtr *filtered = NULL; + + + nfiltered = virTypedParamsFilter(params, ARRAY_CARDINALITY(params), + "foo", &filtered); + if (nfiltered != 3) + goto cleanup; + + for (i = 0; i < nfiltered; i++) { + if (filtered[i] != ¶ms[1 + i * 2]) + goto cleanup; + } + VIR_FREE(filtered); + filtered = NULL; + + nfiltered = virTypedParamsFilter(params, ARRAY_CARDINALITY(params), + "bar", &filtered); + + if (nfiltered != 2) + goto cleanup; + + for (i = 0; i < nfiltered; i++) { + if (filtered[i] != ¶ms[i * 2]) + goto cleanup; + } + + rv = 0; + cleanup: + VIR_FREE(filtered); + return rv; +} + +static int +testTypedParamsPickStrings(const void *opaque ATTRIBUTE_UNUSED) +{ + size_t i, picked; + int rv = -1; + char l = '1'; + const char **strings = NULL; + + virTypedParameter params[] = { + { .field = "bar", .type = VIR_TYPED_PARAM_STRING, + .value = { .s = (char*)"bar1"} }, + { .field = "foo", .type = VIR_TYPED_PARAM_INT }, + { .field = "bar", .type = VIR_TYPED_PARAM_STRING, + .value = { .s = (char*)"bar2"} }, + { .field = "foo", .type = VIR_TYPED_PARAM_INT }, + { .field = "foobar", .type = VIR_TYPED_PARAM_STRING }, + { .field = "bar", .type = VIR_TYPED_PARAM_STRING, + .value = { .s = NULL } }, + { .field = "foo", .type = VIR_TYPED_PARAM_INT }, + { .field = "bar", .type = VIR_TYPED_PARAM_STRING, + .value = { .s = (char*)"bar3"} } + }; + + strings = virTypedParamsPickStrings(params, + ARRAY_CARDINALITY(params), + "bar", &picked); + + for (i = 0; i < picked; i++) { + if (i == 2) { + if (strings[i] != NULL) + goto cleanup; + continue; + } + if (!STREQLEN(strings[i], "bar", 3)) + goto cleanup; + if (strings[i][3] != l++) + goto cleanup; + } + + rv = 0; + cleanup: + VIR_FREE(strings); + return rv; +} + +static int testTypedParamsValidator(void) { size_t i; @@ -159,6 +249,12 @@ mymain(void) if (testTypedParamsValidator() < 0) rv = -1; + if (virtTestRun("Filtering", testTypedParamsFilter, NULL) < 0) + rv = -1; + + if (virtTestRun("Picking Strings", testTypedParamsPickStrings, NULL) < 0) + rv = -1; + if (rv < 0) return EXIT_FAILURE; return EXIT_SUCCESS; -- 1.9.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list