From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from [140.186.70.92] (port=51221 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1OMRK1-0004fw-KT for qemu-devel@nongnu.org; Wed, 09 Jun 2010 15:52:23 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1OMRK0-0000Cc-98 for qemu-devel@nongnu.org; Wed, 09 Jun 2010 15:52:21 -0400 Received: from mx1.redhat.com ([209.132.183.28]:63201) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1OMRJz-0000CN-RI for qemu-devel@nongnu.org; Wed, 09 Jun 2010 15:52:20 -0400 Received: from int-mx04.intmail.prod.int.phx2.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.17]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o59JqIvf008135 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Wed, 9 Jun 2010 15:52:19 -0400 Date: Wed, 9 Jun 2010 16:52:13 -0300 From: Luiz Capitulino Subject: Re: [Qemu-devel] [PATCH 03/19] Add enum handlers for easy & efficient string <-> int conversion Message-ID: <20100609165213.1502ff16@redhat.com> In-Reply-To: <1275921752-29420-4-git-send-email-berrange@redhat.com> References: <1275921752-29420-1-git-send-email-berrange@redhat.com> <1275921752-29420-4-git-send-email-berrange@redhat.com> Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: "Daniel P. Berrange" Cc: qemu-devel@nongnu.org On Mon, 7 Jun 2010 15:42:16 +0100 "Daniel P. Berrange" wrote: > There is quite alot of code using an enumeration of possible > values, which also needs todo conversions to/from a string > representation of enum values. These string <-> int conversions > have been repeated in an adhoc manner throughout the code. >=20 > This makes it hard to report on the list of valid strings, > eg in help output, or todo proper validation in the qemu > config/option parsing routines. >=20 > This addresses the first problem by introducing a standard > set of routines for performing string <-> int conversions > for enums. There are two restrictions on using these helpers, > the first enum value must be 0, and there must be a sentinal > in the enum to provide the max value. >=20 > For each enumeration, three functions will be made available >=20 > - string to int convertor: >=20 > int XXXX_from_string(const char *value); >=20 > Returns -1 if the value was not an allowed string for the > enumeration. Returns >=3D 0 for a valid value >=20 > - int to string convertor >=20 > const char * XXXX_to_string(int value); >=20 > Returns NULL if the value was not a member of the > enumeration. Returns a non-NULL sstring for valid value >=20 > - string list generator >=20 > char * XXXX_to_string_list(void); >=20 > Returns a malloc'd string containing all valid values, > separated by commas. Caller must free the string. >=20 > The general usage pattern is as follows. >=20 > In the header file (eg qemu-option.h): >=20 > enum QemuOptType { > QEMU_OPT_STRING =3D 0, /* no parsing (use string as-is) = */ > QEMU_OPT_BOOL, /* on/off = */ > QEMU_OPT_NUMBER, /* simple number = */ > QEMU_OPT_SIZE, /* size, accepts (K)ilo, (M)ega, (G)iga, (T)era= postfix */ >=20 > QEMU_OPT_LAST > }; > QEMU_ENUM_DECL(qemu_opt_type); >=20 > This declares the function prototypes for the 3 methods > outlined above. >=20 > In the corresponding source file (eg qemu-option.c): >=20 > QEMU_ENUM_IMPL(qemu_opt_type, > QEMU_OPT_LAST, > "string", "bool", "number", "size"); >=20 > This provides the implementation of the 3 methods. If there > are greater/fewer strings provided than the number of values > in the enumeration, this generates a compile time assertion > failure that looks like >=20 > qemu-option.c:35: error: negative width in bit-field =E2=80=98verify_er= ror_if_negative_size__=E2=80=99 >=20 > Signed-off-by: Daniel P. Berrange > --- > Makefile.objs | 2 +- > qemu-enum.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ > qemu-enum.h | 45 +++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 90 insertions(+), 1 deletions(-) > create mode 100644 qemu-enum.c > create mode 100644 qemu-enum.h >=20 > diff --git a/Makefile.objs b/Makefile.objs > index 9796dcb..0ba9966 100644 > --- a/Makefile.objs > +++ b/Makefile.objs > @@ -8,7 +8,7 @@ qobject-obj-y +=3D qerror.o > # block-obj-y is code used by both qemu system emulation and qemu-img > =20 > block-obj-y =3D cutils.o cache-utils.o qemu-malloc.o qemu-option.o modul= e.o > -block-obj-y +=3D nbd.o block.o aio.o aes.o osdep.o qemu-config.o > +block-obj-y +=3D nbd.o block.o aio.o aes.o osdep.o qemu-config.o qemu-en= um.o > block-obj-$(CONFIG_POSIX) +=3D posix-aio-compat.o > block-obj-$(CONFIG_LINUX_AIO) +=3D linux-aio.o > =20 > diff --git a/qemu-enum.c b/qemu-enum.c > new file mode 100644 > index 0000000..9bb33ac > --- /dev/null > +++ b/qemu-enum.c > @@ -0,0 +1,44 @@ > +#include "qemu-enum.h" Missing license text. > + > +int qemu_enum_from_string(const char *const*types, > + unsigned int ntypes, > + const char *type) > +{ > + unsigned int i; > + if (!type) > + return -1; > + > + for (i =3D 0 ; i < ntypes ; i++) > + if (strcmp(types[i], type) =3D=3D 0) > + return i; > + > + return -1; > +} > + > +const char *qemu_enum_to_string(const char *const*types, > + unsigned int ntypes, > + int type) > +{ > + if (type < 0 || type >=3D ntypes) > + return NULL; > + > + return types[type]; > +} > + > +char *qemu_enum_to_string_list(const char *const*types, > + unsigned int ntypes) > +{ > + size_t len =3D 0; > + char *ret; > + int i; > + for (i =3D 0 ; i < ntypes ; i++) > + len +=3D strlen(types[i]) + 2; > + ret =3D qemu_malloc(len); > + *ret =3D '\0'; > + for (i =3D 0 ; i < ntypes ; i++) { > + if (i > 0) > + strcat(ret, ", "); > + strcat(ret, types[i]); > + } > + return ret; > +} > diff --git a/qemu-enum.h b/qemu-enum.h > new file mode 100644 > index 0000000..ff47798 > --- /dev/null > +++ b/qemu-enum.h > @@ -0,0 +1,45 @@ > +#ifndef QEMU_ENUM_H > +#define QEMU_ENUM_H > + > +#include "qemu-common.h" > +#include "verify.h" > + > + > +int qemu_enum_from_string(const char *const*types, > + unsigned int ntypes, > + const char *type); > + > +const char *qemu_enum_to_string(const char *const*types, > + unsigned int ntypes, > + int type); > + > +char *qemu_enum_to_string_list(const char *const*types, > + unsigned int ntypes); > + > +#define QEMU_ENUM_IMPL(name, lastVal, ...) \ > + static const char *const name ## _string_list[] =3D { __VA_ARGS__ };= \ > + char *name ## _to_string_list(void) { \ > + return qemu_enum_to_string_list(name ## _string_list, \ > + ARRAY_SIZE(name ## _string_list)); \ > + } \ > + const char *name ## _to_string(int type) { \ > + return qemu_enum_to_string(name ## _string_list, \ > + ARRAY_SIZE(name ## _string_list), \ > + type); \ > + } \ > + int name ## _from_string(const char *type) { \ > + return qemu_enum_from_string(name ## _string_list, \ > + ARRAY_SIZE(name ## _string_list), \ > + type); \ > + } \ > + extern int (* name ## Verify (void)) \ > + [verify_true (ARRAY_SIZE(name ## _string_list) =3D=3D lastVal)] > + > +# define QEMU_ENUM_DECL(name) \ > + const char *name ## _to_string(int type); \ > + char *name ## _to_string_list(void); \ > + int name ## _from_string(const char*type) > + > + > + > +#endif /* QEMU_ENUM_H */