Remove g_irepository_unregister, add GIRepositoryLoadFlags

svn path=/trunk/; revision=543
This commit is contained in:
Colin Walters 2008-08-30 20:31:12 +00:00
parent e6a68106a2
commit 74651b01bd
2 changed files with 139 additions and 65 deletions

View File

@ -35,6 +35,7 @@ static GSList *search_path = NULL;
struct _GIRepositoryPrivate struct _GIRepositoryPrivate
{ {
GHashTable *typelibs; /* (string) namespace -> GTypelib */ GHashTable *typelibs; /* (string) namespace -> GTypelib */
GHashTable *lazy_typelibs; /* (string) namespace -> GTypelib */
}; };
G_DEFINE_TYPE (GIRepository, g_irepository, G_TYPE_OBJECT); G_DEFINE_TYPE (GIRepository, g_irepository, G_TYPE_OBJECT);
@ -44,6 +45,12 @@ g_irepository_init (GIRepository *repository)
{ {
repository->priv = G_TYPE_INSTANCE_GET_PRIVATE (repository, G_TYPE_IREPOSITORY, repository->priv = G_TYPE_INSTANCE_GET_PRIVATE (repository, G_TYPE_IREPOSITORY,
GIRepositoryPrivate); GIRepositoryPrivate);
repository->priv->typelibs
= g_hash_table_new_full (g_str_hash, g_str_equal,
(GDestroyNotify) NULL,
(GDestroyNotify) g_typelib_free);
repository->priv->lazy_typelibs
= g_hash_table_new (g_str_hash, g_str_equal);
} }
static void static void
@ -76,10 +83,6 @@ init_globals ()
if (default_repository == NULL) if (default_repository == NULL)
{ {
default_repository = g_object_new (G_TYPE_IREPOSITORY, NULL); default_repository = g_object_new (G_TYPE_IREPOSITORY, NULL);
default_repository->priv->typelibs
= g_hash_table_new_full (g_str_hash, g_str_equal,
(GDestroyNotify) NULL,
(GDestroyNotify) g_typelib_free);
} }
if (search_path == NULL) if (search_path == NULL)
@ -135,13 +138,7 @@ static GIRepository *
get_repository (GIRepository *repository) get_repository (GIRepository *repository)
{ {
if (repository != NULL) if (repository != NULL)
{ return repository;
if (repository->priv->typelibs == NULL)
repository->priv->typelibs = g_hash_table_new_full (g_str_hash, g_str_equal,
(GDestroyNotify) NULL,
(GDestroyNotify) g_typelib_free);
return repository;
}
else else
{ {
init_globals (); init_globals ();
@ -149,26 +146,45 @@ get_repository (GIRepository *repository)
} }
} }
static const char * static GTypelib *
register_internal (GIRepository *repository, get_registered_status (GIRepository *repository,
const char *source, const char *namespace,
GTypelib *typelib, gboolean allow_lazy,
GError **error) gboolean *lazy_status)
{
GTypelib *typelib;
repository = get_repository (repository);
if (lazy_status)
*lazy_status = FALSE;
typelib = g_hash_table_lookup (repository->priv->typelibs, namespace);
if (typelib)
return typelib;
typelib = g_hash_table_lookup (repository->priv->lazy_typelibs, namespace);
if (!typelib)
return NULL;
if (lazy_status)
*lazy_status = TRUE;
if (!allow_lazy)
return NULL;
return typelib;
}
static GTypelib *
get_registered (GIRepository *repository,
const char *namespace)
{
return get_registered_status (repository, namespace, TRUE, NULL);
}
static gboolean
load_dependencies_recurse (GIRepository *repository,
GTypelib *typelib,
GError **error)
{ {
Header *header;
const gchar *name;
const char *dependencies_glob;
char **dependencies; char **dependencies;
g_return_val_if_fail (typelib != NULL, FALSE);
header = (Header *)typelib->data;
g_return_val_if_fail (header != NULL, FALSE);
name = g_typelib_get_string (typelib, header->namespace);
dependencies = get_typelib_dependencies (typelib); dependencies = get_typelib_dependencies (typelib);
if (dependencies != NULL) if (dependencies != NULL)
{ {
int i; int i;
@ -177,23 +193,69 @@ register_internal (GIRepository *repository,
{ {
char *dependency = dependencies[i]; char *dependency = dependencies[i];
if (!g_irepository_require (repository, dependency, error)) if (!g_irepository_require (repository, dependency,
0, error))
{ {
g_strfreev (dependencies); g_strfreev (dependencies);
return NULL; return FALSE;
} }
} }
g_strfreev (dependencies); g_strfreev (dependencies);
} }
return TRUE;
}
g_assert (g_hash_table_lookup (repository->priv->typelibs, name) == NULL); static const char *
g_hash_table_insert (repository->priv->typelibs, register_internal (GIRepository *repository,
build_typelib_key (name, source), (void *)typelib); const char *source,
gboolean lazy,
GTypelib *typelib,
GError **error)
{
Header *header;
const gchar *namespace;
gboolean was_loaded;
gboolean currently_lazy;
g_return_val_if_fail (typelib != NULL, FALSE);
header = (Header *)typelib->data;
g_return_val_if_fail (header != NULL, FALSE);
namespace = g_typelib_get_string (typelib, header->namespace);
if (lazy)
{
g_assert (!g_hash_table_lookup (repository->priv->lazy_typelibs,
namespace));
g_hash_table_insert (repository->priv->lazy_typelibs,
build_typelib_key (namespace, source), (void *)typelib);
}
else
{
gpointer value;
char *key;
/* First, try loading all the dependencies */
if (!load_dependencies_recurse (repository, typelib, error))
return NULL;
/* Check if we are transitioning from lazily loaded state */
if (g_hash_table_lookup_extended (repository->priv->lazy_typelibs,
namespace,
(gpointer)&key, &value))
g_hash_table_remove (repository->priv->lazy_typelibs, key);
else
key = build_typelib_key (namespace, source);
g_hash_table_insert (repository->priv->typelibs, key, (void *)typelib);
}
if (typelib->module == NULL) if (typelib->module == NULL)
typelib->module = g_module_open (NULL, 0); typelib->module = g_module_open (NULL, 0);
return name; return namespace;
} }
char ** char **
@ -206,7 +268,7 @@ g_irepository_get_dependencies (GIRepository *repository,
repository = get_repository (repository); repository = get_repository (repository);
typelib = g_hash_table_lookup (repository->priv->typelibs, namespace); typelib = get_registered (repository, namespace);
g_return_val_if_fail (typelib != NULL, NULL); g_return_val_if_fail (typelib != NULL, NULL);
return get_typelib_dependencies (typelib); return get_typelib_dependencies (typelib);
@ -215,31 +277,23 @@ g_irepository_get_dependencies (GIRepository *repository,
const char * const char *
g_irepository_load_typelib (GIRepository *repository, g_irepository_load_typelib (GIRepository *repository,
GTypelib *typelib, GTypelib *typelib,
GIRepositoryLoadFlags flags,
GError **error) GError **error)
{ {
Header *header; Header *header;
const char *namespace; const char *namespace;
gboolean allow_lazy = flags & G_IREPOSITORY_LOAD_FLAG_LAZY;
gboolean is_lazy;
repository = get_repository (repository); repository = get_repository (repository);
header = (Header *) typelib->data; header = (Header *) typelib->data;
namespace = g_typelib_get_string (typelib, header->namespace); namespace = g_typelib_get_string (typelib, header->namespace);
if (g_hash_table_lookup (repository->priv->typelibs, namespace)) if (get_registered_status (repository, namespace, allow_lazy, &is_lazy))
return namespace; return namespace;
return register_internal (repository, "<builtin>", typelib, error); return register_internal (repository, "<builtin>",
} allow_lazy, typelib, error);
void
g_irepository_unregister (GIRepository *repository,
const gchar *namespace)
{
repository = get_repository (repository);
if (!g_hash_table_remove (repository->priv->typelibs, namespace))
{
g_printerr ("namespace '%s' not registered\n", namespace);
}
} }
gboolean gboolean
@ -247,8 +301,7 @@ g_irepository_is_registered (GIRepository *repository,
const gchar *namespace) const gchar *namespace)
{ {
repository = get_repository (repository); repository = get_repository (repository);
return get_registered (repository, namespace) != NULL;
return g_hash_table_lookup (repository->priv->typelibs, namespace) != NULL;
} }
GIRepository * GIRepository *
@ -280,7 +333,7 @@ g_irepository_get_n_infos (GIRepository *repository,
{ {
GTypelib *typelib; GTypelib *typelib;
typelib = g_hash_table_lookup (repository->priv->typelibs, namespace); typelib = get_registered (repository, namespace);
if (typelib) if (typelib)
n_interfaces = ((Header *)typelib->data)->n_local_entries; n_interfaces = ((Header *)typelib->data)->n_local_entries;
@ -289,6 +342,8 @@ g_irepository_get_n_infos (GIRepository *repository,
{ {
g_hash_table_foreach (repository->priv->typelibs, g_hash_table_foreach (repository->priv->typelibs,
count_interfaces, &n_interfaces); count_interfaces, &n_interfaces);
g_hash_table_foreach (repository->priv->lazy_typelibs,
count_interfaces, &n_interfaces);
} }
return n_interfaces; return n_interfaces;
@ -384,13 +439,16 @@ g_irepository_get_info (GIRepository *repository,
{ {
GTypelib *typelib; GTypelib *typelib;
typelib = g_hash_table_lookup (repository->priv->typelibs, namespace); typelib = get_registered (repository, namespace);
if (typelib) if (typelib)
find_interface ((void *)namespace, typelib, &data); find_interface ((void *)namespace, typelib, &data);
} }
else else
g_hash_table_foreach (repository->priv->typelibs, find_interface, &data); {
g_hash_table_foreach (repository->priv->typelibs, find_interface, &data);
g_hash_table_foreach (repository->priv->lazy_typelibs, find_interface, &data);
}
return data.iface; return data.iface;
} }
@ -409,6 +467,7 @@ g_irepository_find_by_gtype (GIRepository *repository,
data.iface = NULL; data.iface = NULL;
g_hash_table_foreach (repository->priv->typelibs, find_interface, &data); g_hash_table_foreach (repository->priv->typelibs, find_interface, &data);
g_hash_table_foreach (repository->priv->lazy_typelibs, find_interface, &data);
return data.iface; return data.iface;
} }
@ -442,13 +501,16 @@ g_irepository_find_by_name (GIRepository *repository,
{ {
GTypelib *typelib; GTypelib *typelib;
typelib = g_hash_table_lookup (repository->priv->typelibs, namespace); typelib = get_registered (repository, namespace);
if (typelib) if (typelib)
find_interface ((void *)namespace, typelib, &data); find_interface ((void *)namespace, typelib, &data);
} }
else else
g_hash_table_foreach (repository->priv->typelibs, find_interface, &data); {
g_hash_table_foreach (repository->priv->typelibs, find_interface, &data);
g_hash_table_foreach (repository->priv->lazy_typelibs, find_interface, &data);
}
return data.iface; return data.iface;
} }
@ -483,6 +545,7 @@ g_irepository_get_namespaces (GIRepository *repository)
repository = get_repository (repository); repository = get_repository (repository);
g_hash_table_foreach (repository->priv->typelibs, collect_namespaces, &list); g_hash_table_foreach (repository->priv->typelibs, collect_namespaces, &list);
g_hash_table_foreach (repository->priv->lazy_typelibs, collect_namespaces, &list);
names = g_malloc0 (sizeof (gchar *) * (g_list_length (list) + 1)); names = g_malloc0 (sizeof (gchar *) * (g_list_length (list) + 1));
i = 0; i = 0;
@ -502,7 +565,7 @@ g_irepository_get_shared_library (GIRepository *repository,
repository = get_repository (repository); repository = get_repository (repository);
typelib = g_hash_table_lookup (repository->priv->typelibs, namespace); typelib = get_registered (repository, namespace);
if (!typelib) if (!typelib)
return NULL; return NULL;
header = (Header *) typelib->data; header = (Header *) typelib->data;
@ -535,7 +598,12 @@ g_irepository_get_typelib_path (GIRepository *repository,
if (!g_hash_table_lookup_extended (repository->priv->typelibs, namespace, if (!g_hash_table_lookup_extended (repository->priv->typelibs, namespace,
&orig_key, &value)) &orig_key, &value))
return NULL; {
if (!g_hash_table_lookup_extended (repository->priv->lazy_typelibs, namespace,
&orig_key, &value))
return NULL;
}
return ((char*)orig_key) + strlen ((char *) orig_key) + 1; return ((char*)orig_key) + strlen ((char *) orig_key) + 1;
} }
@ -543,6 +611,7 @@ g_irepository_get_typelib_path (GIRepository *repository,
* g_irepository_require * g_irepository_require
* @repository: Repository, may be %NULL for the default * @repository: Repository, may be %NULL for the default
* @namespace: GI namespace to use, e.g. "Gtk" * @namespace: GI namespace to use, e.g. "Gtk"
* @flags: Set of %GIRepositoryLoadFlags, may be %0
* @error: a #GError. * @error: a #GError.
* *
* Force the namespace @namespace to be loaded if it isn't * Force the namespace @namespace to be loaded if it isn't
@ -555,6 +624,7 @@ g_irepository_get_typelib_path (GIRepository *repository,
gboolean gboolean
g_irepository_require (GIRepository *repository, g_irepository_require (GIRepository *repository,
const gchar *namespace, const gchar *namespace,
GIRepositoryLoadFlags flags,
GError **error) GError **error)
{ {
GSList *ldir; GSList *ldir;
@ -566,13 +636,12 @@ g_irepository_require (GIRepository *repository,
const gchar *typelib_namespace, *shlib_fname; const gchar *typelib_namespace, *shlib_fname;
GModule *module; GModule *module;
guint32 shlib; guint32 shlib;
GHashTable *table; gboolean allow_lazy = flags & G_IREPOSITORY_LOAD_FLAG_LAZY;
gboolean is_lazy;
repository = get_repository (repository); repository = get_repository (repository);
table = repository->priv->typelibs;
/* don't bother loading a namespace if already registered */ if (get_registered_status (repository, namespace, allow_lazy, &is_lazy))
if (g_hash_table_lookup (table, namespace))
return TRUE; return TRUE;
fname = g_strconcat (namespace, ".typelib", NULL); fname = g_strconcat (namespace, ".typelib", NULL);
@ -617,7 +686,8 @@ g_irepository_require (GIRepository *repository,
} }
g_free (fname); g_free (fname);
if (!register_internal (repository, full_path, typelib, error)) if (!register_internal (repository, full_path, allow_lazy,
typelib, error))
{ {
g_typelib_free (typelib); g_typelib_free (typelib);
g_free (full_path); g_free (full_path);

View File

@ -67,6 +67,10 @@ struct _GIRepositoryClass
GObjectClass parent; GObjectClass parent;
}; };
typedef enum
{
G_IREPOSITORY_LOAD_FLAG_LAZY = 1 << 0
} GIRepositoryLoadFlags;
/* Repository */ /* Repository */
@ -75,9 +79,8 @@ GIRepository *g_irepository_get_default (void);
void g_irepository_prepend_search_path (const char *directory); void g_irepository_prepend_search_path (const char *directory);
const char * g_irepository_load_typelib (GIRepository *repository, const char * g_irepository_load_typelib (GIRepository *repository,
GTypelib *typelib, GTypelib *typelib,
GIRepositoryLoadFlags flags,
GError **error); GError **error);
void g_irepository_unregister (GIRepository *repository,
const gchar *namespace);
gboolean g_irepository_is_registered (GIRepository *repository, gboolean g_irepository_is_registered (GIRepository *repository,
const gchar *namespace); const gchar *namespace);
GIBaseInfo * g_irepository_find_by_name (GIRepository *repository, GIBaseInfo * g_irepository_find_by_name (GIRepository *repository,
@ -85,6 +88,7 @@ GIBaseInfo * g_irepository_find_by_name (GIRepository *repository,
const gchar *name); const gchar *name);
gboolean g_irepository_require (GIRepository *repository, gboolean g_irepository_require (GIRepository *repository,
const char *namespace, const char *namespace,
GIRepositoryLoadFlags flags,
GError **error); GError **error);
gchar ** g_irepository_get_dependencies (GIRepository *repository, gchar ** g_irepository_get_dependencies (GIRepository *repository,
const char *namespace); const char *namespace);