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
This commit is contained in:
Dan Winship 2011-05-19 17:46:36 -04:00 committed by Johan Dahlin
parent 215d83ebb0
commit ff6cada552
4 changed files with 118 additions and 0 deletions

View File

@ -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,

View File

@ -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,

View File

@ -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)])

View File

@ -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)
{