summaryrefslogtreecommitdiff
path: root/girepository/girepository.c
diff options
context:
space:
mode:
authorPhilip Withnall <philip@tecnocode.co.uk>2015-01-31 22:48:56 +0000
committerPhilip Withnall <philip.withnall@collabora.co.uk>2015-02-16 08:49:28 +0000
commit8480bf5f108f72585016254c79d9c495e1b0a4a7 (patch)
tree2578ac864bad36ff27720fd1b931ee7776521349 /girepository/girepository.c
parent6ff0b08ff1982ef60d077ba5e1c11ea605be606b (diff)
downloadgobject-introspection-8480bf5f108f72585016254c79d9c495e1b0a4a7.tar.gz
girepository: Add g_irepository_get_immediate_dependencies()
g_irepository_get_dependencies() is supposed to return the transitive closure of all dependencies of the given namespace. However, it just loads the dependencies field from the typelib, which is supposed to only list immediate dependencies. Introduce a new g_irepository_get_immediate_dependencies() which does this, and rewrite g_irepository_get_dependencies() to build the transitive closure of all its namespace dependencies. This does not require loading any new typelibs, as the transitive closure of dependencies should already have been loaded by g_irepository_require() or g_irepository_load_typelib(). https://bugzilla.gnome.org/show_bug.cgi?id=743782
Diffstat (limited to 'girepository/girepository.c')
-rw-r--r--girepository/girepository.c117
1 files changed, 110 insertions, 7 deletions
diff --git a/girepository/girepository.c b/girepository/girepository.c
index fb91afaa..efc3bded 100644
--- a/girepository/girepository.c
+++ b/girepository/girepository.c
@@ -432,6 +432,89 @@ register_internal (GIRepository *repository,
}
/**
+ * g_irepository_get_immediate_dependencies:
+ * @repository: (nullable): A #GIRepository or %NULL for the singleton
+ * process-global default #GIRepository
+ * @namespace_: Namespace of interest
+ *
+ * Return an array of the immediate versioned dependencies for @namespace_.
+ * Returned strings are of the form <code>namespace-version</code>.
+ *
+ * Note: @namespace_ must have already been loaded using a function
+ * such as g_irepository_require() before calling this function.
+ *
+ * To get the transitive closure of dependencies for @namespace_, use
+ * g_irepository_get_dependencies().
+ *
+ * Returns: (transfer full): Zero-terminated string array of immediate versioned
+ * dependencies
+ *
+ * Since: 1.44
+ */
+char **
+g_irepository_get_immediate_dependencies (GIRepository *repository,
+ const char *namespace)
+{
+ GITypelib *typelib;
+ gchar **deps;
+
+ g_return_val_if_fail (namespace != NULL, NULL);
+
+ repository = get_repository (repository);
+
+ typelib = get_registered (repository, namespace, NULL);
+ g_return_val_if_fail (typelib != NULL, NULL);
+
+ /* Ensure we always return a non-%NULL vector. */
+ deps = get_typelib_dependencies (typelib);
+ if (deps == NULL)
+ deps = g_strsplit ("", "|", 0);
+
+ return deps;
+}
+
+/* Load the transitive closure of dependency namespace-version strings for the
+ * given @typelib. @repository must be non-%NULL. @transitive_dependencies must
+ * be a pre-existing GHashTable<owned utf8, owned utf8> set for storing the
+ * dependencies. */
+static void
+get_typelib_dependencies_transitive (GIRepository *repository,
+ GITypelib *typelib,
+ GHashTable *transitive_dependencies)
+{
+ gchar **immediate_dependencies;
+ guint i;
+
+ immediate_dependencies = get_typelib_dependencies (typelib);
+
+ for (i = 0; immediate_dependencies != NULL && immediate_dependencies[i]; i++)
+ {
+ gchar *dependency;
+ const gchar *last_dash;
+ gchar *dependency_namespace;
+
+ dependency = immediate_dependencies[i];
+
+ /* Steal from the strv. */
+ g_hash_table_add (transitive_dependencies, dependency);
+ immediate_dependencies[i] = NULL;
+
+ /* Recurse for this namespace. */
+ last_dash = strrchr (dependency, '-');
+ dependency_namespace = g_strndup (dependency, last_dash - dependency);
+
+ typelib = get_registered (repository, dependency_namespace, NULL);
+ g_return_if_fail (typelib != NULL);
+ get_typelib_dependencies_transitive (repository, typelib,
+ transitive_dependencies);
+
+ g_free (dependency_namespace);
+ }
+
+ g_free (immediate_dependencies);
+}
+
+/**
* g_irepository_get_dependencies:
* @repository: (allow-none): A #GIRepository or %NULL for the singleton
* process-global default #GIRepository
@@ -444,7 +527,10 @@ register_internal (GIRepository *repository,
* Note: @namespace_ must have already been loaded using a function
* such as g_irepository_require() before calling this function.
*
- * Returns: (transfer full): Zero-terminated string array of versioned
+ * To get only the immediate dependencies for @namespace_, use
+ * g_irepository_get_immediate_dependencies().
+ *
+ * Returns: (transfer full): Zero-terminated string array of all versioned
* dependencies
*/
char **
@@ -452,21 +538,38 @@ g_irepository_get_dependencies (GIRepository *repository,
const char *namespace)
{
GITypelib *typelib;
- gchar **deps;
+ GHashTable *transitive_dependencies; /* set of owned utf8 */
+ GHashTableIter iter;
+ gchar *dependency;
+ GPtrArray *out; /* owned utf8 elements */
g_return_val_if_fail (namespace != NULL, NULL);
repository = get_repository (repository);
+ transitive_dependencies = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, NULL);
+ /* Load the dependencies. */
typelib = get_registered (repository, namespace, NULL);
g_return_val_if_fail (typelib != NULL, NULL);
+ get_typelib_dependencies_transitive (repository, typelib,
+ transitive_dependencies);
- /* Ensure we always return a non-%NULL vector. */
- deps = get_typelib_dependencies (typelib);
- if (deps == NULL)
- deps = g_strsplit ("", "|", 0);
+ /* Convert to a string array. */
+ out = g_ptr_array_new_full (g_hash_table_size (transitive_dependencies),
+ g_free);
+ g_hash_table_iter_init (&iter, transitive_dependencies);
- return deps;
+ while (g_hash_table_iter_next (&iter, (gpointer) &dependency, NULL))
+ {
+ g_ptr_array_add (out, dependency);
+ g_hash_table_iter_steal (&iter);
+ }
+
+ /* Add a NULL terminator. */
+ g_ptr_array_add (out, NULL);
+
+ return (gchar **) g_ptr_array_free (out, FALSE);
}
/**