1 /* -*- Mode: C; c-file-style: "gnu"; -*- */
2 /* GObject introspection: Repository implementation
4 * Copyright (C) 2005 Matthias Clasen
5 * Copyright (C) 2008 Colin Walters <walters@verbum.org>
6 * Copyright (C) 2008 Red Hat, Inc.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
29 #include <glib/gprintf.h>
31 #include "girepository.h"
32 #include "gitypelib-internal.h"
33 #include "girepository-private.h"
34 #include "glib-compat.h"
38 static GStaticMutex globals_lock = G_STATIC_MUTEX_INIT;
39 static GIRepository *default_repository = NULL;
40 static GSList *search_path = NULL;
41 static GSList *override_search_path = NULL;
43 struct _GIRepositoryPrivate
45 GHashTable *typelibs; /* (string) namespace -> GITypelib */
46 GHashTable *lazy_typelibs; /* (string) namespace-version -> GITypelib */
47 GHashTable *info_by_gtype; /* GType -> GIBaseInfo */
48 GHashTable *info_by_error_domain; /* GQuark -> GIBaseInfo */
51 G_DEFINE_TYPE (GIRepository, g_irepository, G_TYPE_OBJECT);
54 g_irepository_init (GIRepository *repository)
56 repository->priv = G_TYPE_INSTANCE_GET_PRIVATE (repository, G_TYPE_IREPOSITORY,
58 repository->priv->typelibs
59 = g_hash_table_new_full (g_str_hash, g_str_equal,
60 (GDestroyNotify) NULL,
61 (GDestroyNotify) g_typelib_free);
62 repository->priv->lazy_typelibs
63 = g_hash_table_new (g_str_hash, g_str_equal);
64 repository->priv->info_by_gtype
65 = g_hash_table_new_full (g_direct_hash, g_direct_equal,
66 (GDestroyNotify) NULL,
67 (GDestroyNotify) g_base_info_unref);
68 repository->priv->info_by_error_domain
69 = g_hash_table_new_full (g_direct_hash, g_direct_equal,
70 (GDestroyNotify) NULL,
71 (GDestroyNotify) g_base_info_unref);
75 g_irepository_finalize (GObject *object)
77 GIRepository *repository = G_IREPOSITORY (object);
79 g_hash_table_destroy (repository->priv->typelibs);
80 g_hash_table_destroy (repository->priv->lazy_typelibs);
81 g_hash_table_destroy (repository->priv->info_by_gtype);
82 g_hash_table_destroy (repository->priv->info_by_error_domain);
84 (* G_OBJECT_CLASS (g_irepository_parent_class)->finalize) (G_OBJECT (repository));
88 g_irepository_class_init (GIRepositoryClass *class)
90 GObjectClass *gobject_class;
92 gobject_class = G_OBJECT_CLASS (class);
94 gobject_class->finalize = g_irepository_finalize;
96 g_type_class_add_private (class, sizeof (GIRepositoryPrivate));
102 g_static_mutex_lock (&globals_lock);
104 if (default_repository == NULL)
106 default_repository = g_object_new (G_TYPE_IREPOSITORY, NULL);
109 if (search_path == NULL)
113 const gchar *type_lib_path_env;
115 /* This variable is intended to take precedence over both the default
116 * search path, as well as anything written into code with g_irepository_prepend_search_path.
118 type_lib_path_env = g_getenv ("GI_TYPELIB_PATH");
121 override_search_path = NULL;
122 if (type_lib_path_env)
127 custom_dirs = g_strsplit (type_lib_path_env, G_SEARCHPATH_SEPARATOR_S, 0);
132 override_search_path = g_slist_prepend (override_search_path, *d);
136 /* ownership of the array content was passed to the list */
137 g_free (custom_dirs);
140 if (override_search_path != NULL)
141 override_search_path = g_slist_reverse (override_search_path);
143 libdir = GOBJECT_INTROSPECTION_LIBDIR;
145 typelib_dir = g_build_filename (libdir, "girepository-1.0", NULL);
147 search_path = g_slist_prepend (search_path, typelib_dir);
149 search_path = g_slist_reverse (search_path);
152 g_static_mutex_unlock (&globals_lock);
156 g_irepository_prepend_search_path (const char *directory)
159 search_path = g_slist_prepend (search_path, g_strdup (directory));
163 * g_irepository_get_search_path:
165 * Returns the search path the GIRepository will use when looking for typelibs.
166 * The string is internal to GIRespository and should not be freed, nor should
169 * Return value: (element-type filename) (transfer none): list of strings
172 g_irepository_get_search_path (void)
178 build_search_path_with_overrides (void)
184 if (override_search_path != NULL)
186 result = g_slist_copy (override_search_path);
187 g_slist_last (result)->next = g_slist_copy (search_path);
190 result = g_slist_copy (search_path);
195 build_typelib_key (const char *name, const char *source)
197 GString *str = g_string_new (name);
198 g_string_append_c (str, '\0');
199 g_string_append (str, source);
200 return g_string_free (str, FALSE);
204 get_typelib_dependencies (GITypelib *typelib)
207 const char *dependencies_glob;
209 header = (Header *)typelib->data;
211 if (header->dependencies == 0)
214 dependencies_glob = g_typelib_get_string (typelib, header->dependencies);
215 return g_strsplit (dependencies_glob, "|", 0);
218 static GIRepository *
219 get_repository (GIRepository *repository)
223 if (repository != NULL)
226 return default_repository;
230 check_version_conflict (GITypelib *typelib,
231 const gchar *namespace,
232 const gchar *expected_version,
233 char **version_conflict)
236 const char *loaded_version;
238 if (expected_version == NULL)
240 if (version_conflict)
241 *version_conflict = NULL;
245 header = (Header*)typelib->data;
246 loaded_version = g_typelib_get_string (typelib, header->nsversion);
247 g_assert (loaded_version != NULL);
249 if (strcmp (expected_version, loaded_version) != 0)
251 if (version_conflict)
252 *version_conflict = (char*)loaded_version;
255 if (version_conflict)
256 *version_conflict = NULL;
261 get_registered_status (GIRepository *repository,
262 const char *namespace,
265 gboolean *lazy_status,
266 char **version_conflict)
269 repository = get_repository (repository);
271 *lazy_status = FALSE;
272 typelib = g_hash_table_lookup (repository->priv->typelibs, namespace);
274 return check_version_conflict (typelib, namespace, version, version_conflict);
275 typelib = g_hash_table_lookup (repository->priv->lazy_typelibs, namespace);
282 return check_version_conflict (typelib, namespace, version, version_conflict);
286 get_registered (GIRepository *repository,
287 const char *namespace,
290 return get_registered_status (repository, namespace, version, TRUE, NULL, NULL);
294 load_dependencies_recurse (GIRepository *repository,
300 dependencies = get_typelib_dependencies (typelib);
302 if (dependencies != NULL)
306 for (i = 0; dependencies[i]; i++)
308 char *dependency = dependencies[i];
309 const char *last_dash;
310 char *dependency_namespace;
311 const char *dependency_version;
313 last_dash = strrchr (dependency, '-');
314 dependency_namespace = g_strndup (dependency, last_dash - dependency);
315 dependency_version = last_dash+1;
317 if (!g_irepository_require (repository, dependency_namespace, dependency_version,
320 g_free (dependency_namespace);
321 g_strfreev (dependencies);
324 g_free (dependency_namespace);
326 g_strfreev (dependencies);
332 register_internal (GIRepository *repository,
339 const gchar *namespace;
340 const gchar *version;
342 g_return_val_if_fail (typelib != NULL, FALSE);
344 header = (Header *)typelib->data;
346 g_return_val_if_fail (header != NULL, FALSE);
348 namespace = g_typelib_get_string (typelib, header->namespace);
349 version = g_typelib_get_string (typelib, header->nsversion);
353 g_assert (!g_hash_table_lookup (repository->priv->lazy_typelibs,
355 g_hash_table_insert (repository->priv->lazy_typelibs,
356 build_typelib_key (namespace, source), (void *)typelib);
363 /* First, try loading all the dependencies */
364 if (!load_dependencies_recurse (repository, typelib, error))
367 /* Check if we are transitioning from lazily loaded state */
368 if (g_hash_table_lookup_extended (repository->priv->lazy_typelibs,
370 (gpointer)&key, &value))
371 g_hash_table_remove (repository->priv->lazy_typelibs, key);
373 key = build_typelib_key (namespace, source);
375 g_hash_table_insert (repository->priv->typelibs, key, (void *)typelib);
382 * g_irepository_get_dependencies:
383 * @repository: (allow-none): A #GIRepository, may be %NULL for the default
384 * @namespace_: Namespace of interest
386 * Return an array of all (transitive) dependencies for namespace
387 * @namespace_, including version. The returned strings are of the
388 * form <code>namespace-version</code>.
390 * Note: The namespace must have already been loaded using a function
391 * such as g_irepository_require() before calling this function.
393 * Returns: (transfer full): Zero-terminated string array of versioned dependencies
396 g_irepository_get_dependencies (GIRepository *repository,
397 const char *namespace)
401 g_return_val_if_fail (namespace != NULL, NULL);
403 repository = get_repository (repository);
405 typelib = get_registered (repository, namespace, NULL);
406 g_return_val_if_fail (typelib != NULL, NULL);
408 return get_typelib_dependencies (typelib);
412 g_irepository_load_typelib (GIRepository *repository,
414 GIRepositoryLoadFlags flags,
418 const char *namespace;
419 const char *nsversion;
420 gboolean allow_lazy = flags & G_IREPOSITORY_LOAD_FLAG_LAZY;
422 char *version_conflict;
424 repository = get_repository (repository);
426 header = (Header *) typelib->data;
427 namespace = g_typelib_get_string (typelib, header->namespace);
428 nsversion = g_typelib_get_string (typelib, header->nsversion);
430 if (get_registered_status (repository, namespace, nsversion, allow_lazy,
431 &is_lazy, &version_conflict))
433 if (version_conflict != NULL)
435 g_set_error (error, G_IREPOSITORY_ERROR,
436 G_IREPOSITORY_ERROR_NAMESPACE_VERSION_CONFLICT,
437 "Attempting to load namespace '%s', version '%s', but '%s' is already loaded",
438 namespace, nsversion, version_conflict);
443 return register_internal (repository, "<builtin>",
444 allow_lazy, typelib, error);
448 * g_irepository_is_registered:
449 * @repository: (allow-none): A #GIRepository, may be %NULL for the default
450 * @namespace_: Namespace of interest
451 * @version: (allow-none): Required version, may be %NULL for latest
453 * Check whether a particular namespace (and optionally, a specific
454 * version thereof) is currently loaded. This function is likely to
455 * only be useful in unusual circumstances; in order to act upon
456 * metadata in the namespace, you should call g_irepository_require()
457 * instead which will ensure the namespace is loaded, and return as
458 * quickly as this function will if it has already been loaded.
460 * Returns: %TRUE if namespace-version is loaded, %FALSE otherwise
463 g_irepository_is_registered (GIRepository *repository,
464 const gchar *namespace,
465 const gchar *version)
467 repository = get_repository (repository);
468 return get_registered (repository, namespace, version) != NULL;
472 * g_irepository_get_default:
474 * Returns the singleton process-global default #GIRepository. It is
475 * not currently supported to have multiple repositories in a
476 * particular process, but this function is provided in the unlikely
477 * eventuality that it would become possible, and as a convenience for
478 * higher level language bindings to conform to the GObject method
481 * All methods on #GIRepository also accept %NULL as an instance
482 * parameter to mean this default repository, which is usually more
485 * Returns: (transfer none): The global singleton #GIRepository
488 g_irepository_get_default (void)
490 return get_repository (NULL);
494 * g_irepository_get_n_infos:
495 * @repository: (allow-none): A #GIRepository, may be %NULL for the default
496 * @namespace_: Namespace to inspect
498 * This function returns the number of metadata entries in
499 * given namespace @namespace_. The namespace must have
500 * already been loaded before calling this function.
502 * Returns: number of metadata entries
505 g_irepository_get_n_infos (GIRepository *repository,
506 const gchar *namespace)
509 gint n_interfaces = 0;
511 g_return_val_if_fail (namespace != NULL, -1);
513 repository = get_repository (repository);
515 typelib = get_registered (repository, namespace, NULL);
517 g_return_val_if_fail (typelib != NULL, -1);
519 n_interfaces = ((Header *)typelib->data)->n_local_entries;
525 * g_irepository_get_info:
526 * @repository: (allow-none): A #GIRepository, may be %NULL for the default
527 * @namespace_: Namespace to inspect
528 * @index: 0-based offset into namespace metadata for entry
530 * This function returns a particular metadata entry in the
531 * given namespace @namespace_. The namespace must have
532 * already been loaded before calling this function.
533 * See g_irepository_get_n_infos() to find the maximum number of
536 * Returns: (transfer full): #GIBaseInfo containing metadata
539 g_irepository_get_info (GIRepository *repository,
540 const gchar *namespace,
546 g_return_val_if_fail (namespace != NULL, NULL);
548 repository = get_repository (repository);
550 typelib = get_registered (repository, namespace, NULL);
552 g_return_val_if_fail (typelib != NULL, NULL);
554 entry = g_typelib_get_dir_entry (typelib, index + 1);
557 return _g_info_new_full (entry->blob_type,
559 NULL, typelib, entry->offset);
563 GIRepository *repository;
567 GITypelib *result_typelib;
572 find_by_gtype_foreach (gpointer key,
576 GITypelib *typelib = (GITypelib*)value;
577 FindByGTypeData *data = datap;
579 if (data->result != NULL)
582 data->result = g_typelib_get_dir_entry_by_gtype (typelib, data->fastpass, data->type);
584 data->result_typelib = typelib;
588 * g_irepository_find_by_gtype:
589 * @repository: (allow-none): A #GIRepository, may be %NULL for the default
590 * @gtype: GType to search for
592 * Searches all loaded namespaces for a particular #GType. Note that
593 * in order to locate the metadata, the namespace corresponding to
594 * the type must first have been loaded. There is currently no
595 * mechanism for determining the namespace which corresponds to an
596 * arbitrary GType - thus, this function will operate most reliably
597 * when you know the GType to originate from be from a loaded namespace.
599 * Returns: (transfer full): #GIBaseInfo representing metadata about @type, or %NULL
602 g_irepository_find_by_gtype (GIRepository *repository,
605 FindByGTypeData data;
608 repository = get_repository (repository);
610 cached = g_hash_table_lookup (repository->priv->info_by_gtype,
614 return g_base_info_ref (cached);
616 data.repository = repository;
617 data.fastpass = TRUE;
619 data.result_typelib = NULL;
622 g_hash_table_foreach (repository->priv->typelibs, find_by_gtype_foreach, &data);
623 if (data.result == NULL)
624 g_hash_table_foreach (repository->priv->lazy_typelibs, find_by_gtype_foreach, &data);
626 /* We do two passes; see comment in find_interface */
627 if (data.result == NULL)
629 data.fastpass = FALSE;
630 g_hash_table_foreach (repository->priv->typelibs, find_by_gtype_foreach, &data);
632 if (data.result == NULL)
633 g_hash_table_foreach (repository->priv->lazy_typelibs, find_by_gtype_foreach, &data);
635 if (data.result != NULL)
637 cached = _g_info_new_full (data.result->blob_type,
639 NULL, data.result_typelib, data.result->offset);
641 g_hash_table_insert (repository->priv->info_by_gtype,
643 g_base_info_ref (cached));
650 * g_irepository_find_by_name:
651 * @repository: (allow-none): A #GIRepository, may be %NULL for the default
652 * @namespace_: Namespace which will be searched
653 * @name: Entry name to find
655 * Searches for a particular entry in a namespace. Before calling
656 * this function for a particular namespace, you must call
657 * g_irepository_require() once to load the namespace, or otherwise
658 * ensure the namespace has already been loaded.
660 * Returns: (transfer full): #GIBaseInfo representing metadata about @name, or %NULL
663 g_irepository_find_by_name (GIRepository *repository,
664 const gchar *namespace,
670 g_return_val_if_fail (namespace != NULL, NULL);
672 repository = get_repository (repository);
673 typelib = get_registered (repository, namespace, NULL);
674 g_return_val_if_fail (typelib != NULL, NULL);
676 entry = g_typelib_get_dir_entry_by_name (typelib, name);
679 return _g_info_new_full (entry->blob_type,
681 NULL, typelib, entry->offset);
685 GIRepository *repository;
688 GITypelib *result_typelib;
690 } FindByErrorDomainData;
693 find_by_error_domain_foreach (gpointer key,
697 GITypelib *typelib = (GITypelib*)value;
698 FindByErrorDomainData *data = datap;
700 if (data->result != NULL)
703 data->result = g_typelib_get_dir_entry_by_error_domain (typelib, data->domain);
705 data->result_typelib = typelib;
709 * g_irepository_find_by_error_domain:
710 * @repository: (allow-none): A #GIRepository, may be %NULL for the default
711 * @domain: a #GError domain
713 * Searches for the enum type corresponding to the given #GError
714 * domain. Before calling this function for a particular namespace,
715 * you must call g_irepository_require() once to load the namespace, or
716 * otherwise ensure the namespace has already been loaded.
718 * Returns: (transfer full): #GIEnumInfo representing metadata about @domain's
719 * enum type, or %NULL
724 g_irepository_find_by_error_domain (GIRepository *repository,
727 FindByErrorDomainData data;
730 repository = get_repository (repository);
732 cached = g_hash_table_lookup (repository->priv->info_by_error_domain,
733 GUINT_TO_POINTER (domain));
736 return g_base_info_ref ((GIBaseInfo *)cached);
738 data.repository = repository;
739 data.domain = domain;
740 data.result_typelib = NULL;
743 g_hash_table_foreach (repository->priv->typelibs, find_by_error_domain_foreach, &data);
744 if (data.result == NULL)
745 g_hash_table_foreach (repository->priv->lazy_typelibs, find_by_error_domain_foreach, &data);
747 if (data.result != NULL)
749 cached = _g_info_new_full (data.result->blob_type,
751 NULL, data.result_typelib, data.result->offset);
753 g_hash_table_insert (repository->priv->info_by_error_domain,
754 GUINT_TO_POINTER (domain),
755 g_base_info_ref (cached));
762 collect_namespaces (gpointer key,
768 *list = g_list_append (*list, key);
772 * g_irepository_get_loaded_namespaces:
773 * @repository: (allow-none): A #GIRepository, may be %NULL for the default
775 * Return the list of currently loaded namespaces.
777 * Returns: (utf8) (transfer full): List of namespaces
780 g_irepository_get_loaded_namespaces (GIRepository *repository)
782 GList *l, *list = NULL;
786 repository = get_repository (repository);
788 g_hash_table_foreach (repository->priv->typelibs, collect_namespaces, &list);
789 g_hash_table_foreach (repository->priv->lazy_typelibs, collect_namespaces, &list);
791 names = g_malloc0 (sizeof (gchar *) * (g_list_length (list) + 1));
793 for (l = list; l; l = l->next)
794 names[i++] = g_strdup (l->data);
801 * g_irepository_get_version:
802 * @repository: (allow-none): A #GIRepository, may be %NULL for the default
803 * @namespace_: Namespace to inspect
805 * This function returns the loaded version associated with the given
806 * namespace @namespace_.
808 * Note: The namespace must have already been loaded using a function
809 * such as g_irepository_require() before calling this function.
811 * Returns: Loaded version
814 g_irepository_get_version (GIRepository *repository,
815 const gchar *namespace)
820 g_return_val_if_fail (namespace != NULL, NULL);
822 repository = get_repository (repository);
824 typelib = get_registered (repository, namespace, NULL);
826 g_return_val_if_fail (typelib != NULL, NULL);
828 header = (Header *) typelib->data;
829 return g_typelib_get_string (typelib, header->nsversion);
833 * g_irepository_get_shared_library:
834 * @repository: (allow-none): A #GIRepository, may be %NULL for the default
835 * @namespace_: Namespace to inspect
837 * This function returns the full path to the shared C library
838 * associated with the given namespace @namespace_. There may be no
839 * shared library path associated, in which case this function will
842 * Note: The namespace must have already been loaded using a function
843 * such as g_irepository_require() before calling this function.
845 * Returns: Full path to shared library, or %NULL if none associated
848 g_irepository_get_shared_library (GIRepository *repository,
849 const gchar *namespace)
854 g_return_val_if_fail (namespace != NULL, NULL);
856 repository = get_repository (repository);
858 typelib = get_registered (repository, namespace, NULL);
860 g_return_val_if_fail (typelib != NULL, NULL);
862 header = (Header *) typelib->data;
863 if (header->shared_library)
864 return g_typelib_get_string (typelib, header->shared_library);
870 * g_irepository_get_c_prefix
871 * @repository: (allow-none): A #GIRepository, may be %NULL for the default
872 * @namespace_: Namespace to inspect
874 * This function returns the "C prefix", or the C level namespace
875 * associated with the given introspection namespace. Each C symbol
876 * starts with this prefix, as well each #GType in the library.
878 * Note: The namespace must have already been loaded using a function
879 * such as g_irepository_require() before calling this function.
881 * Returns: C namespace prefix, or %NULL if none associated
884 g_irepository_get_c_prefix (GIRepository *repository,
885 const gchar *namespace_)
890 g_return_val_if_fail (namespace_ != NULL, NULL);
892 repository = get_repository (repository);
894 typelib = get_registered (repository, namespace_, NULL);
896 g_return_val_if_fail (typelib != NULL, NULL);
898 header = (Header *) typelib->data;
899 if (header->shared_library)
900 return g_typelib_get_string (typelib, header->c_prefix);
906 * g_irepository_get_typelib_path
907 * @repository: (allow-none): Repository, may be %NULL for the default
908 * @namespace_: GI namespace to use, e.g. "Gtk"
910 * If namespace @namespace_ is loaded, return the full path to the
911 * .typelib file it was loaded from. If the typelib for
912 * namespace @namespace_ was included in a shared library, return
913 * the special string "$lt;builtin$gt;".
915 * Returns: Filesystem path (or $lt;builtin$gt;) if successful, %NULL if namespace is not loaded
919 g_irepository_get_typelib_path (GIRepository *repository,
920 const gchar *namespace)
922 gpointer orig_key, value;
924 repository = get_repository (repository);
926 if (!g_hash_table_lookup_extended (repository->priv->typelibs, namespace,
929 if (!g_hash_table_lookup_extended (repository->priv->lazy_typelibs, namespace,
934 return ((char*)orig_key) + strlen ((char *) orig_key) + 1;
937 /* This simple search function looks for a specified namespace-version;
938 it's faster than the full directory listing required for latest version. */
940 find_namespace_version (const gchar *namespace,
941 const gchar *version,
946 GError *error = NULL;
947 GMappedFile *mfile = NULL;
950 fname = g_strdup_printf ("%s-%s.typelib", namespace, version);
952 for (ldir = search_path; ldir; ldir = ldir->next)
954 char *path = g_build_filename (ldir->data, fname, NULL);
956 mfile = g_mapped_file_new (path, FALSE, &error);
960 g_clear_error (&error);
971 parse_version (const char *version,
978 *major = strtol (version, &end, 10);
979 dot = strchr (version, '.');
987 *minor = strtol (dot+1, &end, 10);
988 if (end != (version + strlen (version)))
994 compare_version (const char *v1,
998 int v1_major, v1_minor;
999 int v2_major, v2_minor;
1001 success = parse_version (v1, &v1_major, &v1_minor);
1004 success = parse_version (v2, &v2_major, &v2_minor);
1007 if (v1_major > v2_major)
1009 else if (v2_major > v1_major)
1011 else if (v1_minor > v2_minor)
1013 else if (v2_minor > v1_minor)
1018 struct NamespaceVersionCandidadate
1027 compare_candidate_reverse (struct NamespaceVersionCandidadate *c1,
1028 struct NamespaceVersionCandidadate *c2)
1030 int result = compare_version (c1->version, c2->version);
1031 /* First, check the version */
1034 else if (result < 0)
1038 /* Now check the path index, which says how early in the search path
1039 * we found it. This ensures that of equal version targets, we
1040 * pick the earlier one.
1042 if (c1->path_index == c2->path_index)
1044 else if (c1->path_index > c2->path_index)
1052 free_candidate (struct NamespaceVersionCandidadate *candidate)
1054 g_mapped_file_unref (candidate->mfile);
1055 g_free (candidate->path);
1056 g_free (candidate->version);
1057 g_slice_free (struct NamespaceVersionCandidadate, candidate);
1061 enumerate_namespace_versions (const gchar *namespace,
1062 GSList *search_path)
1064 GSList *candidates = NULL;
1065 GHashTable *found_versions = g_hash_table_new (g_str_hash, g_str_equal);
1066 char *namespace_dash;
1067 char *namespace_typelib;
1069 GError *error = NULL;
1072 namespace_dash = g_strdup_printf ("%s-", namespace);
1073 namespace_typelib = g_strdup_printf ("%s.typelib", namespace);
1076 for (ldir = search_path; ldir; ldir = ldir->next)
1079 const char *dirname;
1082 dirname = (const char*)ldir->data;
1083 dir = g_dir_open (dirname, 0, NULL);
1086 while ((entry = g_dir_read_name (dir)) != NULL)
1089 char *path, *version;
1090 struct NamespaceVersionCandidadate *candidate;
1092 if (!g_str_has_suffix (entry, ".typelib"))
1095 if (g_str_has_prefix (entry, namespace_dash))
1097 const char *last_dash;
1098 const char *name_end;
1101 name_end = strrchr (entry, '.');
1102 last_dash = strrchr (entry, '-');
1103 version = g_strndup (last_dash+1, name_end-(last_dash+1));
1104 if (!parse_version (version, &major, &minor))
1113 if (g_hash_table_lookup (found_versions, version) != NULL)
1118 g_hash_table_insert (found_versions, version, version);
1120 path = g_build_filename (dirname, entry, NULL);
1121 mfile = g_mapped_file_new (path, FALSE, &error);
1126 g_clear_error (&error);
1129 candidate = g_slice_new0 (struct NamespaceVersionCandidadate);
1130 candidate->mfile = mfile;
1131 candidate->path_index = index;
1132 candidate->path = path;
1133 candidate->version = version;
1134 candidates = g_slist_prepend (candidates, candidate);
1140 g_free (namespace_dash);
1141 g_free (namespace_typelib);
1142 g_hash_table_destroy (found_versions);
1147 static GMappedFile *
1148 find_namespace_latest (const gchar *namespace,
1149 GSList *search_path,
1150 gchar **version_ret,
1154 GMappedFile *result = NULL;
1156 *version_ret = NULL;
1159 candidates = enumerate_namespace_versions (namespace, search_path);
1161 if (candidates != NULL)
1163 struct NamespaceVersionCandidadate *elected;
1164 candidates = g_slist_sort (candidates, (GCompareFunc) compare_candidate_reverse);
1166 elected = (struct NamespaceVersionCandidadate *) candidates->data;
1167 /* Remove the elected one so we don't try to free its contents */
1168 candidates = g_slist_delete_link (candidates, candidates);
1170 result = elected->mfile;
1171 *path_ret = elected->path;
1172 *version_ret = elected->version;
1173 g_slice_free (struct NamespaceVersionCandidadate, elected); /* just free the container */
1174 g_slist_foreach (candidates, (GFunc) free_candidate, NULL);
1175 g_slist_free (candidates);
1181 * g_irepository_enumerate_versions:
1182 * @repository: (allow-none): the repository
1183 * @namespace_: GI namespace, e.g. "Gtk"
1185 * Obtain an unordered list of versions (either currently loaded or
1186 * available) for @namespace_ in this @repository.
1188 * Returns: (element-type utf8) (transfer full): the array of versions.
1191 g_irepository_enumerate_versions (GIRepository *repository,
1192 const gchar *namespace_)
1195 GSList *search_path;
1196 GSList *candidates, *link;
1197 const gchar *loaded_version;
1199 search_path = build_search_path_with_overrides ();
1200 candidates = enumerate_namespace_versions (namespace_, search_path);
1201 g_slist_free (search_path);
1203 for (link = candidates; link; link = link->next)
1205 struct NamespaceVersionCandidadate *candidate = link->data;
1206 ret = g_list_prepend (ret, g_strdup (candidate->version));
1207 free_candidate (candidate);
1209 g_slist_free (candidates);
1211 /* The currently loaded version of a namespace is also part of the
1212 * available versions, as it could have been loaded using
1213 * require_private().
1215 if (g_irepository_is_registered (repository, namespace_, NULL))
1217 loaded_version = g_irepository_get_version (repository, namespace_);
1218 if (loaded_version && !g_list_find_custom (ret, loaded_version, g_str_equal))
1219 ret = g_list_prepend (ret, g_strdup (loaded_version));
1226 require_internal (GIRepository *repository,
1227 const gchar *namespace,
1228 const gchar *version,
1229 GIRepositoryLoadFlags flags,
1230 GSList *search_path,
1234 GITypelib *ret = NULL;
1236 GITypelib *typelib = NULL;
1237 const gchar *typelib_namespace, *typelib_version;
1238 gboolean allow_lazy = (flags & G_IREPOSITORY_LOAD_FLAG_LAZY) > 0;
1240 char *version_conflict = NULL;
1242 char *tmp_version = NULL;
1244 g_return_val_if_fail (namespace != NULL, FALSE);
1246 repository = get_repository (repository);
1248 typelib = get_registered_status (repository, namespace, version, allow_lazy,
1249 &is_lazy, &version_conflict);
1253 if (version_conflict != NULL)
1255 g_set_error (error, G_IREPOSITORY_ERROR,
1256 G_IREPOSITORY_ERROR_NAMESPACE_VERSION_CONFLICT,
1257 "Requiring namespace '%s' version '%s', but '%s' is already loaded",
1258 namespace, version, version_conflict);
1262 if (version != NULL)
1264 mfile = find_namespace_version (namespace, version,
1265 search_path, &path);
1266 tmp_version = g_strdup (version);
1270 mfile = find_namespace_latest (namespace, search_path,
1271 &tmp_version, &path);
1276 if (version != NULL)
1277 g_set_error (error, G_IREPOSITORY_ERROR,
1278 G_IREPOSITORY_ERROR_TYPELIB_NOT_FOUND,
1279 "Typelib file for namespace '%s', version '%s' not found",
1280 namespace, version);
1282 g_set_error (error, G_IREPOSITORY_ERROR,
1283 G_IREPOSITORY_ERROR_TYPELIB_NOT_FOUND,
1284 "Typelib file for namespace '%s' (any version) not found",
1290 GError *temp_error = NULL;
1291 typelib = g_typelib_new_from_mapped_file (mfile, &temp_error);
1294 g_set_error (error, G_IREPOSITORY_ERROR,
1295 G_IREPOSITORY_ERROR_TYPELIB_NOT_FOUND,
1296 "Failed to load typelib file '%s' for namespace '%s': %s",
1297 path, namespace, temp_error->message);
1298 g_clear_error (&temp_error);
1302 header = (Header *) typelib->data;
1303 typelib_namespace = g_typelib_get_string (typelib, header->namespace);
1304 typelib_version = g_typelib_get_string (typelib, header->nsversion);
1306 if (strcmp (typelib_namespace, namespace) != 0)
1308 g_set_error (error, G_IREPOSITORY_ERROR,
1309 G_IREPOSITORY_ERROR_NAMESPACE_MISMATCH,
1310 "Typelib file %s for namespace '%s' contains "
1311 "namespace '%s' which doesn't match the file name",
1312 path, namespace, typelib_namespace);
1313 g_typelib_free (typelib);
1316 if (version != NULL && strcmp (typelib_version, version) != 0)
1318 g_set_error (error, G_IREPOSITORY_ERROR,
1319 G_IREPOSITORY_ERROR_NAMESPACE_MISMATCH,
1320 "Typelib file %s for namespace '%s' contains "
1321 "version '%s' which doesn't match the expected version '%s'",
1322 path, namespace, typelib_version, version);
1323 g_typelib_free (typelib);
1327 if (!register_internal (repository, path, allow_lazy,
1330 g_typelib_free (typelib);
1335 g_free (tmp_version);
1341 * g_irepository_require:
1342 * @repository: (allow-none): Repository, may be %NULL for the default
1343 * @namespace_: GI namespace to use, e.g. "Gtk"
1344 * @version: (allow-none): Version of namespace, may be %NULL for latest
1345 * @flags: Set of %GIRepositoryLoadFlags, may be 0
1346 * @error: a #GError.
1348 * Force the namespace @namespace_ to be loaded if it isn't already.
1349 * If @namespace_ is not loaded, this function will search for a
1350 * ".typelib" file using the repository search path. In addition, a
1351 * version @version of namespace may be specified. If @version is
1352 * not specified, the latest will be used.
1354 * Returns: (transfer none): a pointer to the #GITypelib if successful, %NULL otherwise
1357 g_irepository_require (GIRepository *repository,
1358 const gchar *namespace,
1359 const gchar *version,
1360 GIRepositoryLoadFlags flags,
1363 GSList *search_path;
1366 search_path = build_search_path_with_overrides ();
1367 typelib = require_internal (repository, namespace, version, flags,
1368 search_path, error);
1369 g_slist_free (search_path);
1375 * g_irepository_require_private:
1376 * @repository: (allow-none): Repository, may be %NULL for the default
1377 * @typelib_dir: Private directory where to find the requested typelib
1378 * @namespace_: GI namespace to use, e.g. "Gtk"
1379 * @version: (allow-none): Version of namespace, may be %NULL for latest
1380 * @flags: Set of %GIRepositoryLoadFlags, may be 0
1381 * @error: a #GError.
1383 * Force the namespace @namespace_ to be loaded if it isn't already.
1384 * If @namespace_ is not loaded, this function will search for a
1385 * ".typelib" file within the private directory only. In addition, a
1386 * version @version of namespace should be specified. If @version is
1387 * not specified, the latest will be used.
1389 * Returns: (transfer none): a pointer to the #GITypelib if successful, %NULL otherwise
1392 g_irepository_require_private (GIRepository *repository,
1393 const gchar *typelib_dir,
1394 const gchar *namespace,
1395 const gchar *version,
1396 GIRepositoryLoadFlags flags,
1399 GSList search_path = { (gpointer) typelib_dir, NULL };
1401 return require_internal (repository, namespace, version, flags,
1402 &search_path, error);
1406 g_irepository_introspect_cb (const char *option_name,
1411 GError *tmp_error = NULL;
1412 gboolean ret = g_irepository_dump (value, &tmp_error);
1415 g_error ("Failed to extract GType data: %s",
1416 tmp_error->message);
1422 static const GOptionEntry introspection_args[] = {
1423 { "introspect-dump", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_CALLBACK,
1424 g_irepository_introspect_cb, "Dump introspection information",
1425 "infile.txt,outfile.xml" },
1430 * g_irepository_get_option_group: (skip)
1432 * Obtain the option group for girepository, it's used
1433 * by the dumper and for programs that wants to provide
1434 * introspection information
1436 * Returns: (transfer full): the option group
1439 g_irepository_get_option_group (void)
1441 GOptionGroup *group;
1442 group = g_option_group_new ("girepository", "Introspection Options", "Show Introspection Options", NULL, NULL);
1444 g_option_group_add_entries (group, introspection_args);
1449 g_irepository_error_quark (void)
1451 static GQuark quark = 0;
1453 quark = g_quark_from_static_string ("g-irepository-error-quark");
1458 * g_type_tag_to_string:
1459 * @type: the type_tag
1461 * Obtain a string representation of @type
1463 * Returns: the string
1466 g_type_tag_to_string (GITypeTag type)
1470 case GI_TYPE_TAG_VOID:
1472 case GI_TYPE_TAG_BOOLEAN:
1474 case GI_TYPE_TAG_INT8:
1476 case GI_TYPE_TAG_UINT8:
1478 case GI_TYPE_TAG_INT16:
1480 case GI_TYPE_TAG_UINT16:
1482 case GI_TYPE_TAG_INT32:
1484 case GI_TYPE_TAG_UINT32:
1486 case GI_TYPE_TAG_INT64:
1488 case GI_TYPE_TAG_UINT64:
1490 case GI_TYPE_TAG_FLOAT:
1492 case GI_TYPE_TAG_DOUBLE:
1494 case GI_TYPE_TAG_UNICHAR:
1496 case GI_TYPE_TAG_GTYPE:
1498 case GI_TYPE_TAG_UTF8:
1500 case GI_TYPE_TAG_FILENAME:
1502 case GI_TYPE_TAG_ARRAY:
1504 case GI_TYPE_TAG_INTERFACE:
1506 case GI_TYPE_TAG_GLIST:
1508 case GI_TYPE_TAG_GSLIST:
1510 case GI_TYPE_TAG_GHASH:
1512 case GI_TYPE_TAG_ERROR:
1520 * g_info_type_to_string:
1521 * @type: the info type
1523 * Obtain a string representation of @type
1525 * Returns: the string
1528 g_info_type_to_string (GIInfoType type)
1532 case GI_INFO_TYPE_INVALID:
1534 case GI_INFO_TYPE_FUNCTION:
1536 case GI_INFO_TYPE_CALLBACK:
1538 case GI_INFO_TYPE_STRUCT:
1540 case GI_INFO_TYPE_BOXED:
1542 case GI_INFO_TYPE_ENUM:
1544 case GI_INFO_TYPE_FLAGS:
1546 case GI_INFO_TYPE_OBJECT:
1548 case GI_INFO_TYPE_INTERFACE:
1550 case GI_INFO_TYPE_CONSTANT:
1552 case GI_INFO_TYPE_UNION:
1554 case GI_INFO_TYPE_VALUE:
1556 case GI_INFO_TYPE_SIGNAL:
1558 case GI_INFO_TYPE_VFUNC:
1560 case GI_INFO_TYPE_PROPERTY:
1562 case GI_INFO_TYPE_FIELD:
1564 case GI_INFO_TYPE_ARG:
1566 case GI_INFO_TYPE_TYPE:
1568 case GI_INFO_TYPE_UNRESOLVED:
1569 return "unresolved";