[Libosinfo] [libosinfo 2/4] Add type info to osinfo_loader_entity() 'key' argument

Christophe Fergeau cfergeau at redhat.com
Wed Nov 6 13:41:51 UTC 2013


When using 'string(./foo)' as an XPath query, if foo does not exist, an
empty string ("") will be returned. Thus osinfo_loader_string() ignores
empty strings during parsing. This happens during regular parsing as we try
to lookup string(./foo[lang(XX-xx)]) for localized nodes,  and ignore its
result if the XPath query returns ""

However, we want to represent booleans as <foo/>. Boolean values are
currently parsed using osinfo_loader_string(), which means such nodes will
be ignored. By associating type information to the additional keys we want
osinfo_loader_entity() to parse, we'll be able to indicate which values are
booleans, and to parse them accordingly.
---
 osinfo/osinfo_loader.c | 180 ++++++++++++++++++++++++++++---------------------
 1 file changed, 103 insertions(+), 77 deletions(-)

diff --git a/osinfo/osinfo_loader.c b/osinfo/osinfo_loader.c
index 309d0a5..10aff48 100644
--- a/osinfo/osinfo_loader.c
+++ b/osinfo/osinfo_loader.c
@@ -57,6 +57,13 @@ struct _OsinfoLoaderPrivate
     OsinfoDb *db;
 };
 
+struct _OsinfoEntityKey
+{
+    const char *name;
+    GType type;
+};
+typedef struct _OsinfoEntityKey OsinfoEntityKey;
+
 static void
 osinfo_loader_finalize (GObject *object)
 {
@@ -220,7 +227,7 @@ osinfo_loader_doc(const char *xpath,
 
 static void osinfo_loader_entity(OsinfoLoader *loader,
                                  OsinfoEntity *entity,
-                                 const gchar *const *keys,
+                                 const OsinfoEntityKey *keys,
                                  xmlXPathContextPtr ctxt,
                                  xmlNodePtr root,
                                  GError **err)
@@ -229,37 +236,55 @@ static void osinfo_loader_entity(OsinfoLoader *loader,
     const gchar * const *langs = g_get_language_names ();
 
     /* Standard well-known keys first, allow single value only */
-    for (i = 0 ; keys != NULL && keys[i] != NULL; i++) {
-        gchar *value = NULL;
-        gchar *xpath;
+    for (i = 0 ; keys != NULL && keys[i].name != NULL; i++) {
+        gchar *value_str = NULL;
+        gchar *xpath = NULL;
         int j;
 
         /* We are guaranteed to have at least the default "C" locale and we
          * want to ignore that, hence the NULL check on index 'j + 1'.
          */
-        for (j = 0; langs[j + 1] != NULL; j++) {
-            xpath = g_strdup_printf("string(./%s[lang('%s')])", keys[i], langs[j]);
-            value = osinfo_loader_string(xpath, ctxt, err);
-            g_free(xpath);
-            if (error_is_set(err))
-                return;
-
-            if (value != NULL)
-                break;
+        if (keys[i].type == G_TYPE_STRING) {
+            for (j = 0; langs[j + 1] != NULL; j++) {
+                xpath = g_strdup_printf("string(./%s[lang('%s')])",
+                                        keys[i].name, langs[j]);
+                value_str = osinfo_loader_string(xpath, ctxt, err);
+                g_free(xpath);
+                xpath = NULL;
+                if (error_is_set(err))
+                    return;
+
+                if (value_str != NULL)
+                    break;
+            }
         }
 
-        if (value == NULL) {
-            xpath = g_strdup_printf("string(./%s)", keys[i]);
-            value = osinfo_loader_string(xpath, ctxt, err);
-            g_free(xpath);
-            if (error_is_set(err))
-                return;
+        switch (keys[i].type) {
+            case G_TYPE_STRING:
+                xpath = g_strdup_printf("string(./%s)", keys[i].name);
+                if (value_str == NULL) {
+                    value_str = osinfo_loader_string(xpath, ctxt, err);
+                }
+                break;
+            default:
+                g_warn_if_reached();
+                break;
         }
-
-        if (value) {
-            osinfo_entity_set_param(entity, keys[i], value);
-            g_free(value);
+        g_free(xpath);
+
+        switch (keys[i].type) {
+            case G_TYPE_STRING:
+                if (value_str) {
+                    osinfo_entity_set_param(entity, keys[i].name, value_str);
+                    g_free(value_str);
+                    value_str = NULL;
+                }
+                break;
+            default:
+                g_warn_if_reached();
+                break;
         }
+        g_warn_if_fail(value_str == NULL);
     }
 
     /* Then any site specific custom keys. x-... Can be repeated */
@@ -352,16 +377,16 @@ static void osinfo_loader_device(OsinfoLoader *loader,
                                  GError **err)
 {
     gchar *id = (gchar *)xmlGetProp(root, BAD_CAST "id");
-    const gchar *const keys[] = {
-        OSINFO_DEVICE_PROP_VENDOR,
-        OSINFO_DEVICE_PROP_VENDOR_ID,
-        OSINFO_DEVICE_PROP_PRODUCT,
-        OSINFO_DEVICE_PROP_PRODUCT_ID,
-        OSINFO_DEVICE_PROP_SUBSYSTEM,
-        OSINFO_DEVICE_PROP_BUS_TYPE,
-        OSINFO_DEVICE_PROP_CLASS,
-        OSINFO_DEVICE_PROP_NAME,
-        NULL,
+    const OsinfoEntityKey keys[] = {
+        { OSINFO_DEVICE_PROP_VENDOR, G_TYPE_STRING },
+        { OSINFO_DEVICE_PROP_VENDOR_ID, G_TYPE_STRING },
+        { OSINFO_DEVICE_PROP_PRODUCT, G_TYPE_STRING },
+        { OSINFO_DEVICE_PROP_PRODUCT_ID, G_TYPE_STRING },
+        { OSINFO_DEVICE_PROP_SUBSYSTEM, G_TYPE_STRING },
+        { OSINFO_DEVICE_PROP_BUS_TYPE, G_TYPE_STRING },
+        { OSINFO_DEVICE_PROP_CLASS, G_TYPE_STRING },
+        { OSINFO_DEVICE_PROP_NAME, G_TYPE_STRING },
+        { NULL, G_TYPE_INVALID }
     };
     if (!id) {
         OSINFO_ERROR(err, _("Missing device id property"));
@@ -388,9 +413,9 @@ static void osinfo_loader_device_link(OsinfoLoader *loader,
         return;
 
     for (i = 0 ; i < nrelated ; i++) {
-        const gchar *keys[] = {
-            OSINFO_DEVICELINK_PROP_DRIVER,
-            NULL,
+        const OsinfoEntityKey keys[] = {
+            { OSINFO_DEVICELINK_PROP_DRIVER, G_TYPE_STRING },
+            { NULL, G_TYPE_INVALID }
         };
         gchar *id = (gchar *)xmlGetProp(related[i], BAD_CAST "id");
         if (!id) {
@@ -461,16 +486,16 @@ static void osinfo_loader_product(OsinfoLoader *loader,
                                   xmlNodePtr root,
                                   GError **err)
 {
-    const gchar *const keys[] = {
-        OSINFO_PRODUCT_PROP_NAME,
-        OSINFO_PRODUCT_PROP_VENDOR,
-        OSINFO_PRODUCT_PROP_VERSION,
-        OSINFO_PRODUCT_PROP_LOGO,
-        OSINFO_PRODUCT_PROP_SHORT_ID,
-        OSINFO_PRODUCT_PROP_RELEASE_DATE,
-        OSINFO_PRODUCT_PROP_EOL_DATE,
-        OSINFO_PRODUCT_PROP_CODENAME,
-        NULL,
+    const OsinfoEntityKey keys[] = {
+        { OSINFO_PRODUCT_PROP_NAME, G_TYPE_STRING },
+        { OSINFO_PRODUCT_PROP_VENDOR, G_TYPE_STRING },
+        { OSINFO_PRODUCT_PROP_VERSION, G_TYPE_STRING },
+        { OSINFO_PRODUCT_PROP_LOGO, G_TYPE_STRING },
+        { OSINFO_PRODUCT_PROP_SHORT_ID, G_TYPE_STRING },
+        { OSINFO_PRODUCT_PROP_RELEASE_DATE, G_TYPE_STRING },
+        { OSINFO_PRODUCT_PROP_EOL_DATE, G_TYPE_STRING },
+        { OSINFO_PRODUCT_PROP_CODENAME, G_TYPE_STRING },
+        { NULL, G_TYPE_INVALID }
     };
 
     osinfo_loader_entity(loader, OSINFO_ENTITY(product), keys, ctxt, root, err);
@@ -663,12 +688,12 @@ static OsinfoAvatarFormat *osinfo_loader_avatar_format(OsinfoLoader *loader,
                                                        GError **err)
 {
     OsinfoAvatarFormat *avatar_format;
-    const gchar *const keys[] = {
-        OSINFO_AVATAR_FORMAT_PROP_MIME_TYPE,
-        OSINFO_AVATAR_FORMAT_PROP_WIDTH,
-        OSINFO_AVATAR_FORMAT_PROP_HEIGHT,
-        OSINFO_AVATAR_FORMAT_PROP_ALPHA,
-        NULL
+    const OsinfoEntityKey keys[] = {
+        { OSINFO_AVATAR_FORMAT_PROP_MIME_TYPE, G_TYPE_STRING },
+        { OSINFO_AVATAR_FORMAT_PROP_WIDTH, G_TYPE_STRING },
+        { OSINFO_AVATAR_FORMAT_PROP_HEIGHT, G_TYPE_STRING },
+        { OSINFO_AVATAR_FORMAT_PROP_ALPHA, G_TYPE_STRING },
+        { NULL, G_TYPE_INVALID }
     };
 
     avatar_format = osinfo_avatar_format_new();
@@ -689,16 +714,16 @@ static void osinfo_loader_install_script(OsinfoLoader *loader,
                                          GError **err)
 {
     gchar *id = (gchar *)xmlGetProp(root, BAD_CAST "id");
-    const gchar *const keys[] = {
-        OSINFO_INSTALL_SCRIPT_PROP_PROFILE,
-        OSINFO_INSTALL_SCRIPT_PROP_PRODUCT_KEY_FORMAT,
-        OSINFO_INSTALL_SCRIPT_PROP_PATH_FORMAT,
-        OSINFO_INSTALL_SCRIPT_PROP_EXPECTED_FILENAME,
-        OSINFO_INSTALL_SCRIPT_PROP_CAN_PRE_INSTALL_DRIVERS,
-        OSINFO_INSTALL_SCRIPT_PROP_CAN_POST_INSTALL_DRIVERS,
-        OSINFO_INSTALL_SCRIPT_PROP_PRE_INSTALL_DRIVERS_SIGNING_REQ,
-        OSINFO_INSTALL_SCRIPT_PROP_POST_INSTALL_DRIVERS_SIGNING_REQ,
-        NULL
+    const OsinfoEntityKey keys[] = {
+        { OSINFO_INSTALL_SCRIPT_PROP_PROFILE, G_TYPE_STRING },
+        { OSINFO_INSTALL_SCRIPT_PROP_PRODUCT_KEY_FORMAT, G_TYPE_STRING },
+        { OSINFO_INSTALL_SCRIPT_PROP_PATH_FORMAT, G_TYPE_STRING },
+        { OSINFO_INSTALL_SCRIPT_PROP_EXPECTED_FILENAME, G_TYPE_STRING },
+        { OSINFO_INSTALL_SCRIPT_PROP_CAN_PRE_INSTALL_DRIVERS, G_TYPE_STRING },
+        { OSINFO_INSTALL_SCRIPT_PROP_CAN_POST_INSTALL_DRIVERS, G_TYPE_STRING },
+        { OSINFO_INSTALL_SCRIPT_PROP_PRE_INSTALL_DRIVERS_SIGNING_REQ, G_TYPE_STRING },
+        { OSINFO_INSTALL_SCRIPT_PROP_POST_INSTALL_DRIVERS_SIGNING_REQ, G_TYPE_STRING },
+        { NULL, G_TYPE_INVALID }
     };
     gchar *value = NULL;
     xmlNodePtr *nodes = NULL;
@@ -784,11 +809,11 @@ static OsinfoMedia *osinfo_loader_media (OsinfoLoader *loader,
     xmlChar *installer = xmlGetProp(root, BAD_CAST OSINFO_MEDIA_PROP_INSTALLER);
     xmlChar *installer_reboots =
             xmlGetProp(root, BAD_CAST OSINFO_MEDIA_PROP_INSTALLER_REBOOTS);
-    const gchar *const keys[] = {
-        OSINFO_MEDIA_PROP_URL,
-        OSINFO_MEDIA_PROP_KERNEL,
-        OSINFO_MEDIA_PROP_INITRD,
-        NULL
+    const OsinfoEntityKey keys[] = {
+        { OSINFO_MEDIA_PROP_URL, G_TYPE_STRING },
+        { OSINFO_MEDIA_PROP_KERNEL, G_TYPE_STRING },
+        { OSINFO_MEDIA_PROP_INITRD, G_TYPE_STRING },
+        { NULL, G_TYPE_INVALID }
     };
 
     OsinfoMedia *media = osinfo_media_new(id, arch);
@@ -879,12 +904,12 @@ static OsinfoTree *osinfo_loader_tree (OsinfoLoader *loader,
     guint i;
 
     gchar *arch = (gchar *)xmlGetProp(root, BAD_CAST "arch");
-    const gchar *const keys[] = {
-        OSINFO_TREE_PROP_URL,
-        OSINFO_TREE_PROP_KERNEL,
-        OSINFO_TREE_PROP_INITRD,
-        OSINFO_TREE_PROP_BOOT_ISO,
-        NULL
+    const OsinfoEntityKey keys[] = {
+        { OSINFO_TREE_PROP_URL, G_TYPE_STRING },
+        { OSINFO_TREE_PROP_KERNEL, G_TYPE_STRING },
+        { OSINFO_TREE_PROP_INITRD, G_TYPE_STRING },
+        { OSINFO_TREE_PROP_BOOT_ISO, G_TYPE_STRING },
+        { NULL, G_TYPE_INVALID }
     };
 
     OsinfoTree *tree = osinfo_tree_new(id, arch);
@@ -1088,11 +1113,12 @@ static void osinfo_loader_os(OsinfoLoader *loader,
     int nnodes;
 
     gchar *id = (gchar *)xmlGetProp(root, BAD_CAST "id");
-    const gchar *const keys[] = {
-        OSINFO_OS_PROP_FAMILY,
-        OSINFO_OS_PROP_DISTRO,
-        NULL
+    const OsinfoEntityKey keys[] = {
+        { OSINFO_OS_PROP_FAMILY, G_TYPE_STRING },
+        { OSINFO_OS_PROP_DISTRO, G_TYPE_STRING },
+        { NULL, G_TYPE_INVALID }
     };
+
     if (!id) {
         OSINFO_ERROR(err, _("Missing os id property"));
         return;
-- 
1.8.4.2




More information about the Libosinfo mailing list