There are quite a few places in our code where we have to convert from a string to an int enumeration, and vica-verca. This is tedious code to write, and I'm about to introduce a tonne more enumerations in the new generic domain XML parser / generator. So I reckon its time for some helper APIs The current pattern is that we have an enumeration enum virStoragePoolDisk { VIR_STORAGE_POOL_DISK_DOS, VIR_STORAGE_POOL_DISK_DVH, VIR_STORAGE_POOL_DISK_GPT, VIR_STORAGE_POOL_DISK_MAC, VIR_STORAGE_POOL_DISK_BSD, VIR_STORAGE_POOL_DISK_PC98, VIR_STORAGE_POOL_DISK_SUN, }; And then 2 helpers static int virStorageBackendDiskPoolFormatFromString(const char *format) { if (STREQ(format, "dos")) return VIR_STORAGE_POOL_DISK_DOS; if (STREQ(format, "dvh")) return VIR_STORAGE_POOL_DISK_DVH; if (STREQ(format, "gpt")) return VIR_STORAGE_POOL_DISK_GPT; if (STREQ(format, "mac")) return VIR_STORAGE_POOL_DISK_MAC; if (STREQ(format, "bsd")) return VIR_STORAGE_POOL_DISK_BSD; if (STREQ(format, "pc98")) return VIR_STORAGE_POOL_DISK_PC98; if (STREQ(format, "sun")) return VIR_STORAGE_POOL_DISK_SUN; return -1; } static const char * virStorageBackendDiskPoolFormatToString(int format) { switch (format) { case VIR_STORAGE_POOL_DISK_DOS: return "dos"; case VIR_STORAGE_POOL_DISK_DVH: return "dvh"; case VIR_STORAGE_POOL_DISK_GPT: return "gpt"; case VIR_STORAGE_POOL_DISK_MAC: return "mac"; case VIR_STORAGE_POOL_DISK_BSD: return "bsd"; case VIR_STORAGE_POOL_DISK_PC98: return "pc98"; case VIR_STORAGE_POOL_DISK_SUN: return "sun"; } return NULL; } This patch adds 2 generic ToString and FromString methods to the util.c module, which take a list of strings, in the same order as the enum int virEnumFromString(const char *const*types, int ntypes, const char *type); const char *virEnumToString(const char *const*types, int ntypes, int type); Passing around the list of strings (the "char *const*types" arg) is a little tedious, so there are 2 macros to simplify this by defining wrappers around the virEnumXXX functions VIR_ENUM_DECL(name) will define the function prototypes, and should be used in a header file, while VIR_ENUM_IMPL(name, maxvals, types) will define the implementation, type checked at compile time So, going back to the earlier example - we need to adapt the enum to add a sentinal at the end enum virStoragePoolDisk { VIR_STORAGE_POOL_DISK_DOS, VIR_STORAGE_POOL_DISK_DVH, VIR_STORAGE_POOL_DISK_GPT, VIR_STORAGE_POOL_DISK_MAC, VIR_STORAGE_POOL_DISK_BSD, VIR_STORAGE_POOL_DISK_PC98, VIR_STORAGE_POOL_DISK_SUN, VIR_STORAGE_POOL_DISK_LAST }; Then, we can provide the ToString and FromString methods with just VIR_ENUM_DECL(virStoragePoolDisk) VIR_ENUM_IMPL(virStoragePoolDisk, VIR_STORAGE_POOL_DISK_LAST, "dos", "dvh", "gpt", "mac", "bsd", "pc98", "sun") This has compile time checking to ensure there are enough strings for every enumeration value. Daniel. diff -r bc1615919490 src/util.c --- a/src/util.c Fri Jun 13 15:43:20 2008 +0100 +++ b/src/util.c Fri Jun 13 18:52:39 2008 +0100 @@ -798,3 +798,24 @@ return idx; } +int virEnumFromString(const char *const*types, + int ntypes, + const char *type) +{ + int i; + for (i = 0 ; i < ntypes ; i++) + if (STREQ(types[i], type)) + return i; + + return -1; +} + +const char *virEnumToString(const char *const*types, + int ntypes, + int type) +{ + if (type < 0 || type >= ntypes) + return NULL; + + return types[type]; +} diff -r bc1615919490 src/util.h --- a/src/util.h Fri Jun 13 15:43:20 2008 +0100 +++ b/src/util.h Fri Jun 13 18:52:39 2008 +0100 @@ -25,6 +25,7 @@ #define __VIR_UTIL_H__ #include "util-lib.h" +#include "verify.h" int virExec(virConnectPtr conn, char **argv, int *retpid, int infd, int *outfd, int *errfd); @@ -88,4 +89,31 @@ int virDiskNameToIndex(const char* str); + +int virEnumFromString(const char *const*types, + int ntypes, + const char *type); + +const char *virEnumToString(const char *const*types, + int ntypes, + int type); + +#define VIR_ENUM_IMPL(name, lastVal, ...) \ + static const char const *name ## TypeList[] = { __VA_ARGS__ }; \ + verify(ARRAY_CARDINALITY(name ## TypeList) == lastVal); \ + const char *name ## TypeToString(int type) { \ + return virEnumToString(name ## TypeList, \ + ARRAY_CARDINALITY(name ## TypeList), \ + type); \ + } \ + int name ## TypeFromString(const char *type) { \ + return virEnumFromString(name ## TypeList, \ + ARRAY_CARDINALITY(name ## TypeList), \ + type); \ + } + +#define VIR_ENUM_DECL(name) \ + const char *name ## TypeToString(int type); \ + int name ## TypeFromString(const char*type); + #endif /* __VIR_UTIL_H__ */ -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list