From 3377335508b4e5faa380cbb49d7c6ecd2276007f Mon Sep 17 00:00:00 2001 From: Peter Krempa Date: Thu, 19 Sep 2019 09:20:49 +0200 Subject: [PATCH] util: typedparam: Simplify handling of lists of typed parameters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce a new set of helpers including a new data structure which simplifies keeping and construction of lists of typed parameters. The use of VIR_RESIZE_N in the virTypedParamsAdd API has performance benefits but requires passing around 3 arguments. Use of them lead to a set of macros with embedded jumps used in the qemu statistics code. This patch introduces 'virTypedParamList' type which aggregates the necessary list-keeping variables and also a new set of functions to add new typed parameters to a list. These new helpers use printf-like format string and arguments to format the argument name as the stats code often uses indexed typed parameters. The accessor function then allows extracting the typed parameter list in the same format as virTypedParamsAdd* functions would do. One additional benefit is also that the list function can easily be used with VIR_AUTOPTR. Signed-off-by: Peter Krempa Reviewed-by: Ján Tomko --- src/libvirt_private.syms | 9 ++ src/util/virtypedparam.c | 222 +++++++++++++++++++++++++++++++++++++++ src/util/virtypedparam.h | 52 +++++++++ 3 files changed, 283 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 8af9e7c95e..287e63bffa 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -3232,6 +3232,15 @@ virTypedParameterAssign; virTypedParameterToString; virTypedParameterTypeFromString; virTypedParameterTypeToString; +virTypedParamListAddBoolean; +virTypedParamListAddDouble; +virTypedParamListAddInt; +virTypedParamListAddLLong; +virTypedParamListAddString; +virTypedParamListAddUInt; +virTypedParamListAddULLong; +virTypedParamListFree; +virTypedParamListStealParams; virTypedParamsCheck; virTypedParamsCopy; virTypedParamsDeserialize; diff --git a/src/util/virtypedparam.c b/src/util/virtypedparam.c index d1b251fae6..7b3fcd118e 100644 --- a/src/util/virtypedparam.c +++ b/src/util/virtypedparam.c @@ -254,6 +254,23 @@ virTypedParameterAssignValueVArgs(virTypedParameterPtr param, } +static int +virTypedParameterAssignValue(virTypedParameterPtr param, + bool copystr, + int type, + ...) +{ + int ret; + va_list ap; + + va_start(ap, type); + ret = virTypedParameterAssignValueVArgs(param, type, ap, copystr); + va_end(ap); + + return ret; +} + + /* Assign name, type, and the appropriately typed arg to param; in the * case of a string, the caller is assumed to have malloc'd a string, * or can pass NULL to have this function malloc an empty string. @@ -725,3 +742,208 @@ virTypedParamsSerialize(virTypedParameterPtr params, virTypedParamsRemoteFree(params_val, nparams); return rv; } + + +void +virTypedParamListFree(virTypedParamListPtr list) +{ + if (!list) + return; + + virTypedParamsFree(list->par, list->npar); + VIR_FREE(list); +} + + +size_t +virTypedParamListStealParams(virTypedParamListPtr list, + virTypedParameterPtr *params) +{ + size_t ret = list->npar; + + VIR_STEAL_PTR(*params, list->par); + list->npar = 0; + list->par_alloc = 0; + + return ret; +} + + +static int ATTRIBUTE_FMT_PRINTF(2, 0) +virTypedParamSetNameVPrintf(virTypedParameterPtr par, + const char *fmt, + va_list ap) +{ + if (vsnprintf(par->field, VIR_TYPED_PARAM_FIELD_LENGTH, fmt, ap) > VIR_TYPED_PARAM_FIELD_LENGTH) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Field name too long")); + return -1; + } + + return 0; +} + + +static virTypedParameterPtr +virTypedParamListExtend(virTypedParamListPtr list) +{ + if (VIR_RESIZE_N(list->par, list->par_alloc, list->npar, 1) < 0) + return NULL; + + list->npar++; + + return list->par + (list->npar - 1); +} + + +int +virTypedParamListAddInt(virTypedParamListPtr list, + int value, + const char *namefmt, + ...) +{ + virTypedParameterPtr par; + va_list ap; + int ret; + + if (!(par = virTypedParamListExtend(list)) || + virTypedParameterAssignValue(par, true, VIR_TYPED_PARAM_INT, value) < 0) + return -1; + + va_start(ap, namefmt); + ret = virTypedParamSetNameVPrintf(par, namefmt, ap); + va_end(ap); + + return ret; +} + + +int +virTypedParamListAddUInt(virTypedParamListPtr list, + unsigned int value, + const char *namefmt, + ...) +{ + virTypedParameterPtr par; + va_list ap; + int ret; + + if (!(par = virTypedParamListExtend(list)) || + virTypedParameterAssignValue(par, true, VIR_TYPED_PARAM_UINT, value) < 0) + return -1; + + va_start(ap, namefmt); + ret = virTypedParamSetNameVPrintf(par, namefmt, ap); + va_end(ap); + + return ret; +} + + +int +virTypedParamListAddLLong(virTypedParamListPtr list, + long long value, + const char *namefmt, + ...) +{ + virTypedParameterPtr par; + va_list ap; + int ret; + + if (!(par = virTypedParamListExtend(list)) || + virTypedParameterAssignValue(par, true, VIR_TYPED_PARAM_LLONG, value) < 0) + return -1; + + va_start(ap, namefmt); + ret = virTypedParamSetNameVPrintf(par, namefmt, ap); + va_end(ap); + + return ret; +} + + +int +virTypedParamListAddULLong(virTypedParamListPtr list, + unsigned long long value, + const char *namefmt, + ...) +{ + virTypedParameterPtr par; + va_list ap; + int ret; + + if (!(par = virTypedParamListExtend(list)) || + virTypedParameterAssignValue(par, true, VIR_TYPED_PARAM_ULLONG, value) < 0) + return -1; + + va_start(ap, namefmt); + ret = virTypedParamSetNameVPrintf(par, namefmt, ap); + va_end(ap); + + return ret; +} + + +int +virTypedParamListAddString(virTypedParamListPtr list, + const char *value, + const char *namefmt, + ...) +{ + virTypedParameterPtr par; + va_list ap; + int ret; + + if (!(par = virTypedParamListExtend(list)) || + virTypedParameterAssignValue(par, true, VIR_TYPED_PARAM_STRING, value) < 0) + return -1; + + va_start(ap, namefmt); + ret = virTypedParamSetNameVPrintf(par, namefmt, ap); + va_end(ap); + + return ret; +} + + +int +virTypedParamListAddBoolean(virTypedParamListPtr list, + bool value, + const char *namefmt, + ...) +{ + virTypedParameterPtr par; + va_list ap; + int ret; + + if (!(par = virTypedParamListExtend(list)) || + virTypedParameterAssignValue(par, true, VIR_TYPED_PARAM_BOOLEAN, value) < 0) + return -1; + + va_start(ap, namefmt); + ret = virTypedParamSetNameVPrintf(par, namefmt, ap); + va_end(ap); + + return ret; +} + + +int +virTypedParamListAddDouble(virTypedParamListPtr list, + double value, + const char *namefmt, + ...) +{ + virTypedParameterPtr par; + va_list ap; + int ret; + + if (!(par = virTypedParamListExtend(list)) || + virTypedParameterAssignValue(par, true, VIR_TYPED_PARAM_DOUBLE, value) < 0) + return -1; + + va_start(ap, namefmt); + ret = virTypedParamSetNameVPrintf(par, namefmt, ap); + va_end(ap); + + return ret; +} diff --git a/src/util/virtypedparam.h b/src/util/virtypedparam.h index cad6953f5d..34cff1b2b3 100644 --- a/src/util/virtypedparam.h +++ b/src/util/virtypedparam.h @@ -24,6 +24,7 @@ #include "internal.h" #include "virutil.h" #include "virenum.h" +#include "virautoclean.h" /** * VIR_TYPED_PARAM_MULTIPLE: @@ -128,3 +129,54 @@ VIR_ENUM_DECL(virTypedParameter); VIR_FREE(_value); \ } \ } while (0) + +typedef struct _virTypedParamList virTypedParamList; +typedef virTypedParamList *virTypedParamListPtr; + +struct _virTypedParamList { + virTypedParameterPtr par; + size_t npar; + size_t par_alloc; +}; + +void virTypedParamListFree(virTypedParamListPtr list); +VIR_DEFINE_AUTOPTR_FUNC(virTypedParamList, virTypedParamListFree); + +size_t virTypedParamListStealParams(virTypedParamListPtr list, + virTypedParameterPtr *params); + +int virTypedParamListAddInt(virTypedParamListPtr list, + int value, + const char *namefmt, + ...) + ATTRIBUTE_FMT_PRINTF(3, 4) ATTRIBUTE_RETURN_CHECK; +int virTypedParamListAddUInt(virTypedParamListPtr list, + unsigned int value, + const char *namefmt, + ...) + ATTRIBUTE_FMT_PRINTF(3, 4) ATTRIBUTE_RETURN_CHECK; +int virTypedParamListAddLLong(virTypedParamListPtr list, + long long value, + const char *namefmt, + ...) + ATTRIBUTE_FMT_PRINTF(3, 4) ATTRIBUTE_RETURN_CHECK; +int virTypedParamListAddULLong(virTypedParamListPtr list, + unsigned long long value, + const char *namefmt, + ...) + ATTRIBUTE_FMT_PRINTF(3, 4) ATTRIBUTE_RETURN_CHECK; +int virTypedParamListAddString(virTypedParamListPtr list, + const char *value, + const char *namefmt, + ...) + ATTRIBUTE_FMT_PRINTF(3, 4) ATTRIBUTE_RETURN_CHECK; +int virTypedParamListAddBoolean(virTypedParamListPtr list, + bool value, + const char *namefmt, + ...) + ATTRIBUTE_FMT_PRINTF(3, 4) ATTRIBUTE_RETURN_CHECK; +int virTypedParamListAddDouble(virTypedParamListPtr list, + double value, + const char *namefmt, + ...) + ATTRIBUTE_FMT_PRINTF(3, 4) ATTRIBUTE_RETURN_CHECK;