summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Winship <danw@gnome.org>2011-05-19 17:46:36 -0400
committerJohan Dahlin <jdahlin@litl.com>2011-08-13 09:42:38 -0300
commitd3a7314ba46b32e0dc215ad7d54fbf888ac519d0 (patch)
tree98e20ed4d73aa54559f65cb469d0a5c861ee0aad
parentd92fb1e2433e6c64e47da6277e30e8fad455e719 (diff)
downloadgobject-introspection-d3a7314ba46b32e0dc215ad7d54fbf888ac519d0.tar.gz
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
-rw-r--r--girepository/girepository.c83
-rw-r--r--girepository/girepository.h2
-rw-r--r--girepository/gitypelib-internal.h3
-rw-r--r--girepository/gitypelib.c30
-rw-r--r--tests/repository/gitestrepo.c9
5 files changed, 127 insertions, 0 deletions
diff --git a/girepository/girepository.c b/girepository/girepository.c
index 1afba0c8..a2a778d9 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 fddcf8c1..9e99f6e3 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 49fbe4e3..1dde5163 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 3869a6d2..f610d458 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 316ee3d2..e7c3ae45 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);
}