--- a/gplugin/gplugin-manager.c Tue Feb 25 04:25:47 2020 +0000
+++ b/gplugin/gplugin-manager.c Tue Feb 25 04:37:20 2020 +0000
@@ -61,7 +61,8 @@
GHashTable *plugins_filename_view;
+ GHashTable *loaders_by_extension; @@ -76,8 +77,8 @@
GList *(*get_paths)(GPluginManager *manager);
- void (*register_loader)(GPluginManager *manager, GType type);
- void (*unregister_loader)(GPluginManager *manager, GType type);
+ gboolean (*register_loader)(GPluginManager *manager, GType type, GError **error); + gboolean (*unregister_loader)(GPluginManager *manager, GType type, GError **error); void (*refresh)(GPluginManager *manager);
@@ -156,6 +157,31 @@
+ * gplugin_manager_find_loader_by_type: + * @manager: The #GPluginManager instance. + * @type: The #GType of the loader to find. + * Looks up a #GPluginLoader instance by its type. + * Returns: (transfer none): The #GPluginLoader instance or %NULL. +gplugin_manager_find_loader_by_type(GPluginManager *manager, GType type) { + g_return_val_if_fail(GPLUGIN_IS_MANAGER(manager), NULL); + g_return_val_if_fail(g_type_is_a(type, GPLUGIN_TYPE_LOADER), NULL); + for(l = manager->loaders; l; l = l->next) { + if(G_OBJECT_TYPE(l->data) == type) { + return GPLUGIN_LOADER(l->data); /******************************************************************************
*****************************************************************************/
@@ -219,37 +245,37 @@
return manager->paths->head;
-gplugin_manager_real_register_loader(GPluginManager *manager,
+gplugin_manager_real_register_loader(GPluginManager *manager, GType type, GPluginLoader *loader = NULL;
- GPluginLoaderClass *lo_class = NULL;
+ GSList *l = NULL, *exts = NULL; + g_return_val_if_fail(g_type_is_a(type, GPLUGIN_TYPE_LOADER), FALSE); - g_return_if_fail(g_type_is_a(type, GPLUGIN_TYPE_LOADER));
+ loader = gplugin_manager_find_loader_by_type(manager, type); + if(GPLUGIN_IS_LOADER(loader)) { + g_set_error(error, GPLUGIN_DOMAIN, 0, + _("loader %s was already registered"), g_type_name(type)); /* Create the loader instance first. If we can't create it, we bail */
loader = g_object_new(type, NULL);
if(!GPLUGIN_IS_LOADER(loader)) {
- g_warning(_("failed to create loader instance for %s"),
+ g_set_error(error, GPLUGIN_DOMAIN, 0, + _("failed to create loader instance for %s"),
- /* grab the class of the loader */
- lo_class = GPLUGIN_LOADER_GET_CLASS(loader);
- g_warning(_("failed to get the loader class for %s"), g_type_name(type));
- g_object_unref(G_OBJECT(loader));
+ manager->loaders = g_slist_prepend(manager->loaders, + g_object_ref(G_OBJECT(loader)));
- for(l = gplugin_loader_class_get_supported_extensions(lo_class);
+ exts = gplugin_loader_get_supported_extensions(loader); + for(l = exts; l; l = l->next) { GSList *existing = NULL, *ll = NULL;
const gchar *ext = (const gchar *)l->data;
@@ -257,7 +283,7 @@
* we can prepend our loader. But before we add ours, we remove any
* old copies we might have of ours.
- existing = g_hash_table_lookup(manager->loaders, ext);
+ existing = g_hash_table_lookup(manager->loaders_by_extension, ext); for(ll = existing; ll; ll = ll->next) {
if(G_OBJECT_TYPE(ll->data) == type) {
GPluginLoader *old = GPLUGIN_LOADER(ll->data);
@@ -273,40 +299,48 @@
existing = g_slist_prepend(existing, g_object_ref(G_OBJECT(loader)));
/* Now insert the updated slist back into the hash table */
- g_hash_table_insert(manager->loaders, g_strdup(ext), existing);
+ g_hash_table_insert(manager->loaders_by_extension, g_strdup(ext), /* make a note that we need to refresh */
manager->refresh_needed = TRUE;
/* we remove our initial reference from the loader now to avoid a leak */
g_object_unref(G_OBJECT(loader));
-gplugin_manager_real_unregister_loader(GPluginManager *manager,
+gplugin_manager_real_unregister_loader(GPluginManager *manager, GType type, - GPluginLoaderClass *klass = NULL;
+ GPluginLoader *loader = NULL; + GSList *l = NULL, *exts = NULL; - g_return_if_fail(g_type_is_a(type, GPLUGIN_TYPE_LOADER));
+ g_return_val_if_fail(g_type_is_a(type, GPLUGIN_TYPE_LOADER), FALSE); - klass = g_type_class_ref(type);
+ loader = gplugin_manager_find_loader_by_type(manager, type); + if(!GPLUGIN_IS_LOADER(loader)) { + g_set_error(error, GPLUGIN_DOMAIN, 0, + _("loader %s is not registered"), g_type_name(type)); - for(exts = gplugin_loader_class_get_supported_extensions(klass);
- exts; exts = exts->next) {
+ exts = gplugin_loader_get_supported_extensions(loader); + for(l = exts; l; l = l->next) {
ext = (const gchar *)exts->data;
- los = g_hash_table_lookup(manager->loaders, ext);
+ los = g_hash_table_lookup(manager->loaders_by_extension, ext); - for(l = los; l; l = l->next) {
- GPluginLoader *lo = GPLUGIN_LOADER(l->data);
+ for(ll = los; ll; ll = ll->next) { + GPluginLoader *lo = GPLUGIN_LOADER(ll->data); /* check if this is not the loader we're looking for */
if(G_OBJECT_TYPE(lo) != type)
@@ -318,10 +352,12 @@
los = g_slist_remove(los, lo);
- g_hash_table_insert(manager->loaders, g_strdup(ext), los);
- g_hash_table_remove(manager->loaders, ext);
+ g_hash_table_insert(manager->loaders_by_extension, + g_hash_table_remove(manager->loaders_by_extension, ext); /* kill our ref to the loader */
g_object_unref(G_OBJECT(lo));
@@ -330,8 +366,12 @@
- g_type_class_unref(klass);
+ manager->loaders = g_slist_remove(manager->loaders, loader); + g_object_unref(G_OBJECT(loader)); @@ -392,9 +432,8 @@
/* grab the list of loaders for this extension */
- for(l = g_hash_table_lookup(manager->loaders, e->extension); l;
+ l = g_hash_table_lookup(manager->loaders_by_extension, e->extension); + for(; l; l = l->next) { @@ -850,11 +889,15 @@
/* destroy the filename view */
g_clear_pointer(&manager->plugins_filename_view, g_hash_table_destroy);
+ /* clean up our list of loaders */ + g_slist_free_full(manager->loaders, g_object_unref); + manager->loaders = NULL; /* free all the data in the loaders hash table and destroy it */
- g_hash_table_foreach_remove(manager->loaders,
+ g_hash_table_foreach_remove(manager->loaders_by_extension, gplugin_manager_remove_list_value,
- g_clear_pointer(&manager->loaders, g_hash_table_destroy);
+ g_clear_pointer(&manager->loaders_by_extension, g_hash_table_destroy); /* call the base class's destructor */
G_OBJECT_CLASS(gplugin_manager_parent_class)->finalize(obj);
@@ -1011,18 +1054,18 @@
manager->plugins_filename_view =
g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_object_unref);
- /* The loaders hash table is keyed on the supported extensions of the
- * loader. Which means that a loader that supports multiple extensions
- * will be in the table multiple times.
+ /* The loaders_by_extension hash table is keyed on the supported extensions + * of the loader. Which means that a loader that supports multiple + * extensions will be in the table multiple times. * We deal with collisions by using a GSList for the value which will hold
* references to instances of the actual loaders.
- * Storing this in this method allows up to quickly figure out which loader
+ * Storing this in this method allows us to quickly figure out which loader * to use by the filename and helps us to avoid iterating the loaders table
+ manager->loaders_by_extension = g_hash_table_new_full(gplugin_manager_str_hash, g_str_equal,
@@ -1032,13 +1075,22 @@
*****************************************************************************/
gplugin_manager_private_init(void) {
instance = g_object_new(GPLUGIN_TYPE_MANAGER, NULL);
- gplugin_manager_register_loader(GPLUGIN_TYPE_NATIVE_LOADER);
+ if(!gplugin_manager_register_loader(GPLUGIN_TYPE_NATIVE_LOADER, &error)) { + g_error("failed to register loader: %s", error->message); + g_error("failed to register loader: unknown failure"); dependency_regex = g_regex_new(dependency_pattern, 0, 0, NULL);
@@ -1201,37 +1253,55 @@
* gplugin_manager_register_loader:
* @type: #GType of a #GPluginLoader.
+ * @error: (out) (nullable): The return address for a #GError. * Registers @type as an available loader.
+ * Returns: %TRUE if the loader was successfully register, %FALSE otherwise
-gplugin_manager_register_loader(GType type) {
+gplugin_manager_register_loader(GType type, GError **error) { GPluginManager *manager = GPLUGIN_MANAGER_INSTANCE;
GPluginManagerClass *klass = NULL;
- g_return_if_fail(GPLUGIN_IS_MANAGER(manager));
+ g_return_val_if_fail(GPLUGIN_IS_MANAGER(manager), FALSE); klass = GPLUGIN_MANAGER_GET_CLASS(manager);
if(klass && klass->register_loader)
- klass->register_loader(manager, type);
+ return klass->register_loader(manager, type, error); + g_set_error(error, GPLUGIN_DOMAIN, 0, + "register_loader method not implemented"); * gplugin_manager_unregister_loader:
* @type: #GType of a #GPluginLoader.
+ * @error: (out) (nullable): The return address for a #GError. * Unregisters @type as an available loader.
+ * Returns: %TRUE if the loader was successfully unregistered, %FALSE + * otherwise with @error set.
-gplugin_manager_unregister_loader(GType type) {
+gplugin_manager_unregister_loader(GType type, GError **error) { GPluginManager *manager = GPLUGIN_MANAGER_INSTANCE;
GPluginManagerClass *klass = NULL;
- g_return_if_fail(GPLUGIN_IS_MANAGER(manager));
+ g_return_val_if_fail(GPLUGIN_IS_MANAGER(manager), FALSE); klass = GPLUGIN_MANAGER_GET_CLASS(manager);
if(klass && klass->unregister_loader)
- klass->unregister_loader(manager, type);
+ return klass->unregister_loader(manager, type, error); + g_set_error(error, GPLUGIN_DOMAIN, 0, + "unregister_loader method not implemented"); --- a/gplugin/gplugin-native-loader.c Tue Feb 25 04:25:47 2020 +0000
+++ b/gplugin/gplugin-native-loader.c Tue Feb 25 04:37:20 2020 +0000
@@ -101,12 +101,12 @@
* GPluginLoaderInterface API
*****************************************************************************/
-gplugin_native_loader_class_supported_extensions(G_GNUC_UNUSED GPluginLoaderClass *klass) {
+gplugin_native_loader_supported_extensions(G_GNUC_UNUSED GPluginLoader *l) { GSList *exts = g_slist_append(NULL, G_MODULE_SUFFIX);
#if defined(__APPLE__) || defined(__MACH__)
- /* G_MODULE_SUFFIX only requests so on not windows, and both .so and
- * .dylib are use on macos, so add dylib if we're on macos.
+ /* G_MODULE_SUFFIX only requests `.so` on not windows, and both .so and + * .dylib are used on macos, so add dylib if we're on macos. * See: https://gitlab.gnome.org/GNOME/glib/issues/1413
exts = g_slist_append(exts, "dylib");
@@ -304,7 +304,7 @@
GPLUGIN_LOADER_CLASS(klass);
loader_class->supported_extensions =
- gplugin_native_loader_class_supported_extensions;
+ gplugin_native_loader_supported_extensions; loader_class->query = gplugin_native_loader_query;
loader_class->load = gplugin_native_loader_load;
loader_class->unload = gplugin_native_loader_unload;
--- a/lua/gplugin-lua-loader.c Tue Feb 25 04:25:47 2020 +0000
+++ b/lua/gplugin-lua-loader.c Tue Feb 25 04:37:20 2020 +0000
@@ -81,7 +81,7 @@
* GPluginLoaderInterface API
*****************************************************************************/
-gplugin_lua_loader_class_supported_extensions(G_GNUC_UNUSED GPluginLoaderClass *klass) {
+gplugin_lua_loader_supported_extensions(G_GNUC_UNUSED GPluginLoader *l) { return g_slist_append(NULL, "lua");
@@ -174,7 +174,7 @@
GPluginLoaderClass *loader_class = GPLUGIN_LOADER_CLASS(klass);
loader_class->supported_extensions =
- gplugin_lua_loader_class_supported_extensions;
+ gplugin_lua_loader_supported_extensions; loader_class->query = gplugin_lua_loader_query;
loader_class->load = gplugin_lua_loader_load;
loader_class->unload = gplugin_lua_loader_unload;
--- a/perl/gplugin-perl-loader.c Tue Feb 25 04:25:47 2020 +0000
+++ b/perl/gplugin-perl-loader.c Tue Feb 25 04:37:20 2020 +0000
@@ -167,7 +167,7 @@
* GPluginLoaderInterface API
*****************************************************************************/
-gplugin_perl_loader_class_supported_extensions(G_GNUC_UNUSED GPluginLoaderClass *klass) {
+gplugin_perl_loader_supported_extensions(G_GNUC_UNUSED GPluginLoader *l) { return g_slist_append(NULL, "pl");
@@ -279,7 +279,7 @@
GPluginLoaderClass *loader_class = GPLUGIN_LOADER_CLASS(klass);
loader_class->supported_extensions =
- gplugin_perl_loader_class_supported_extensions;
+ gplugin_perl_loader_supported_extensions; loader_class->query = gplugin_perl_loader_query;
loader_class->load = gplugin_perl_loader_load;
loader_class->unload = gplugin_perl_loader_unload;
--- a/python/gplugin-python3-loader.c Tue Feb 25 04:25:47 2020 +0000
+++ b/python/gplugin-python3-loader.c Tue Feb 25 04:37:20 2020 +0000
@@ -41,7 +41,7 @@
* GPluginLoader Implementation
*****************************************************************************/
-gplugin_python3_loader_class_supported_extensions(G_GNUC_UNUSED GPluginLoaderClass *klass) {
+gplugin_python3_loader_supported_extensions(G_GNUC_UNUSED GPluginLoader *l) { return g_slist_append(NULL, "py");
@@ -356,7 +356,7 @@
GPluginLoaderClass *loader_class = GPLUGIN_LOADER_CLASS(klass);
loader_class->supported_extensions =
- gplugin_python3_loader_class_supported_extensions;
+ gplugin_python3_loader_supported_extensions; loader_class->query = gplugin_python3_loader_query;
loader_class->load = gplugin_python3_loader_load;
loader_class->unload = gplugin_python3_loader_unload;
--- a/tcc/gplugin-tcc-loader.c Tue Feb 25 04:25:47 2020 +0000
+++ b/tcc/gplugin-tcc-loader.c Tue Feb 25 04:37:20 2020 +0000
@@ -33,12 +33,8 @@
* GPluginLoaderInterface API
*****************************************************************************/
-gplugin_tcc_loader_class_supported_extensions(G_GNUC_UNUSED const GPluginLoaderClass *klass) {
- exts = g_slist_append(exts, "c");
+gplugin_tcc_loader_supported_extensions(G_GNUC_UNUSED GPluginLoader *l) { + return g_list_append(NULL, "c"); @@ -161,7 +157,7 @@
GPluginLoaderClass *loader_class = GPLUGIN_LOADER_CLASS(klass);
loader_class->supported_extensions =
- gplugin_tcc_loader_class_supported_extensions;
+ gplugin_tcc_loader_supported_extensions; loader_class->query = gplugin_tcc_loader_query;
loader_class->load = gplugin_tcc_loader_load;
loader_class->unload = gplugin_tcc_loader_unload;