[libvirt] PATCH: Helper for enumerations

Daniel P. Berrange berrange at redhat.com
Sun Jun 15 20:59:38 UTC 2008


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




More information about the libvir-list mailing list