From: Dan Winship Date: Thu, 19 May 2011 21:46:36 +0000 (-0400) Subject: Add g_irepository_find_by_error_domain() X-Git-Tag: GOBJECT_INTROSPECTION_1_29_17~67^2~11 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=d3a7314ba46b32e0dc215ad7d54fbf888ac519d0;p=platform%2Fupstream%2Fgobject-introspection.git 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 --- 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 #include +#include + 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); }