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 :|