[gobject-introspection] Add g_irepository_find_by_error_domain()



commit c4c1de663f0c42875d5dd029d910d6c37e90ec8a
Author: Dan Winship <danw gnome org>
Date:   Thu May 19 17:46:36 2011 -0400

    Add g_irepository_find_by_error_domain()
    
    Add a method to look up a GIEnumInfo given its associated error quark.
    
    Based on a patch from Colin Walters.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=602516

 girepository/girepository.c       |   83 +++++++++++++++++++++++++++++++++++++
 girepository/girepository.h       |    2 +
 girepository/gitypelib-internal.h |    3 +
 girepository/gitypelib.c          |   30 +++++++++++++
 tests/repository/gitestrepo.c     |    9 ++++
 5 files changed, 127 insertions(+), 0 deletions(-)
---
diff --git a/girepository/girepository.c b/girepository/girepository.c
index 1afba0c..a2a778d 100644
--- a/girepository/girepository.c
+++ b/girepository/girepository.c
@@ -45,6 +45,7 @@ struct _GIRepositoryPrivate
   GHashTable *typelibs; /* (string) namespace -> GITypelib */
   GHashTable *lazy_typelibs; /* (string) namespace-version -> GITypelib */
   GHashTable *info_by_gtype; /* GType -> GIBaseInfo */
+  GHashTable *info_by_error_domain; /* GQuark -> GIBaseInfo */
 };
 
 G_DEFINE_TYPE (GIRepository, g_irepository, G_TYPE_OBJECT);
@@ -64,6 +65,10 @@ g_irepository_init (GIRepository *repository)
     = g_hash_table_new_full (g_direct_hash, g_direct_equal,
                              (GDestroyNotify) NULL,
                              (GDestroyNotify) g_base_info_unref);
+  repository->priv->info_by_error_domain
+    = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+                             (GDestroyNotify) NULL,
+                             (GDestroyNotify) g_base_info_unref);
 }
 
 static void
@@ -74,6 +79,7 @@ g_irepository_finalize (GObject *object)
   g_hash_table_destroy (repository->priv->typelibs);
   g_hash_table_destroy (repository->priv->lazy_typelibs);
   g_hash_table_destroy (repository->priv->info_by_gtype);
+  g_hash_table_destroy (repository->priv->info_by_error_domain);
 
   (* G_OBJECT_CLASS (g_irepository_parent_class)->finalize) (G_OBJECT (repository));
 }
@@ -675,6 +681,83 @@ g_irepository_find_by_name (GIRepository *repository,
 			   NULL, typelib, entry->offset);
 }
 
+typedef struct {
+  GIRepository *repository;
+  GQuark domain;
+
+  GITypelib *result_typelib;
+  DirEntry *result;
+} FindByErrorDomainData;
+
+static void
+find_by_error_domain_foreach (gpointer key,
+			      gpointer value,
+			      gpointer datap)
+{
+  GITypelib *typelib = (GITypelib*)value;
+  FindByErrorDomainData *data = datap;
+
+  if (data->result != NULL)
+    return;
+
+  data->result = g_typelib_get_dir_entry_by_error_domain (typelib, data->domain);
+  if (data->result)
+    data->result_typelib = typelib;
+}
+
+/**
+ * g_irepository_find_by_error_domain:
+ * @repository: (allow-none): A #GIRepository, may be %NULL for the default
+ * @domain: a #GError domain
+ *
+ * Searches for the enum type corresponding to the given #GError
+ * domain. Before calling this function for a particular namespace,
+ * you must call g_irepository_require() once to load the namespace, or
+ * otherwise ensure the namespace has already been loaded.
+ *
+ * Returns: (transfer full): #GIEnumInfo representing metadata about @domain's
+ * enum type, or %NULL
+ *
+ * Since: 1.29.17
+ */
+GIEnumInfo *
+g_irepository_find_by_error_domain (GIRepository *repository,
+				    GQuark        domain)
+{
+  FindByErrorDomainData data;
+  GIEnumInfo *cached;
+
+  repository = get_repository (repository);
+
+  cached = g_hash_table_lookup (repository->priv->info_by_error_domain,
+				GUINT_TO_POINTER (domain));
+
+  if (cached != NULL)
+    return g_base_info_ref ((GIBaseInfo *)cached);
+
+  data.repository = repository;
+  data.domain = domain;
+  data.result_typelib = NULL;
+  data.result = NULL;
+
+  g_hash_table_foreach (repository->priv->typelibs, find_by_error_domain_foreach, &data);
+  if (data.result == NULL)
+    g_hash_table_foreach (repository->priv->lazy_typelibs, find_by_error_domain_foreach, &data);
+
+  if (data.result != NULL)
+    {
+      cached = _g_info_new_full (data.result->blob_type,
+				 repository,
+				 NULL, data.result_typelib, data.result->offset);
+
+      g_hash_table_insert (repository->priv->info_by_error_domain,
+			   GUINT_TO_POINTER (domain),
+			   g_base_info_ref (cached));
+      return cached;
+    }
+  return NULL;
+}
+
 static void
 collect_namespaces (gpointer key,
 		    gpointer value,
diff --git a/girepository/girepository.h b/girepository/girepository.h
index fddcf8c..9e99f6e 100644
--- a/girepository/girepository.h
+++ b/girepository/girepository.h
@@ -123,6 +123,8 @@ gint          g_irepository_get_n_infos   (GIRepository *repository,
 GIBaseInfo *  g_irepository_get_info      (GIRepository *repository,
 					   const gchar  *namespace_,
 					   gint          index);
+GIEnumInfo *  g_irepository_find_by_error_domain (GIRepository *repository,
+						  GQuark        domain);
 const gchar * g_irepository_get_typelib_path   (GIRepository *repository,
 						const gchar  *namespace_);
 const gchar * g_irepository_get_shared_library (GIRepository *repository,
diff --git a/girepository/gitypelib-internal.h b/girepository/gitypelib-internal.h
index 49fbe4e..1dde516 100644
--- a/girepository/gitypelib-internal.h
+++ b/girepository/gitypelib-internal.h
@@ -1117,6 +1117,9 @@ DirEntry *g_typelib_get_dir_entry_by_gtype (GITypelib *typelib,
 					    gboolean   fastpass,
 					    GType      gtype);
 
+DirEntry *g_typelib_get_dir_entry_by_error_domain (GITypelib *typelib,
+						   GQuark     error_domain);
+
 void      g_typelib_check_sanity (void);
 
 #define   g_typelib_get_string(typelib,offset) ((const gchar*)&(typelib->data)[(offset)])
diff --git a/girepository/gitypelib.c b/girepository/gitypelib.c
index 3869a6d..f610d45 100644
--- a/girepository/gitypelib.c
+++ b/girepository/gitypelib.c
@@ -249,6 +249,36 @@ g_typelib_get_dir_entry_by_gtype (GITypelib *typelib,
   return NULL;
 }
 
+DirEntry *
+g_typelib_get_dir_entry_by_error_domain (GITypelib *typelib,
+					 GQuark     error_domain)
+{
+  Header *header = (Header *)typelib->data;
+  guint n_entries = header->n_local_entries;
+  const char *domain_string = g_quark_to_string (error_domain);
+  DirEntry *entry;
+  guint i;
+
+  for (i = 1; i <= n_entries; i++)
+    {
+      EnumBlob *blob;
+      const char *enum_domain_string;
+
+      entry = g_typelib_get_dir_entry (typelib, i);
+      if (entry->blob_type != BLOB_TYPE_ENUM)
+	continue;
+
+      blob = (EnumBlob *)(&typelib->data[entry->offset]);
+      if (!blob->error_domain)
+	continue;
+
+      enum_domain_string = g_typelib_get_string (typelib, blob->error_domain);
+      if (strcmp (domain_string, enum_domain_string) == 0)
+	return entry;
+    }
+  return NULL;
+}
+
 void
 g_typelib_check_sanity (void)
 {
diff --git a/tests/repository/gitestrepo.c b/tests/repository/gitestrepo.c
index 316ee3d..e7c3ae4 100644
--- a/tests/repository/gitestrepo.c
+++ b/tests/repository/gitestrepo.c
@@ -5,6 +5,8 @@
 #include <string.h>
 #include <unistd.h>
 
+#include <gio/gio.h>
+
 void test_constructor_return_type(GIBaseInfo* object_info);
 
 void
@@ -42,6 +44,7 @@ main(int argc, char **argv)
   GError *error = NULL;
   GIBaseInfo *info;
   GIBaseInfo *siginfo;
+  GIEnumInfo *errorinfo;
   GType gtype;
 
   g_type_init ();
@@ -123,5 +126,11 @@ main(int argc, char **argv)
     g_assert (strcmp (g_base_info_get_name ((GIBaseInfo*)invoker), "get_display") == 0);
   }
 
+  /* Error quark tests */
+  errorinfo = g_irepository_find_by_error_domain (repo, G_RESOLVER_ERROR);
+  g_assert (errorinfo != NULL);
+  g_assert (g_base_info_get_type ((GIBaseInfo *)errorinfo) == GI_INFO_TYPE_ENUM);
+  g_assert (strcmp (g_base_info_get_name ((GIBaseInfo*)errorinfo), "ResolverError") == 0);
+
   exit(0);
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]