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"
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 -> GTypelib */
46 GHashTable *lazy_typelibs; /* (string) namespace-version -> GTypelib */
47 GHashTable *info_by_gtype; /* GType -> GIBaseInfo */
50 G_DEFINE_TYPE (GIRepository, g_irepository, G_TYPE_OBJECT);
53 g_irepository_init (GIRepository *repository)
55 repository->priv = G_TYPE_INSTANCE_GET_PRIVATE (repository, G_TYPE_IREPOSITORY,
57 repository->priv->typelibs
58 = g_hash_table_new_full (g_str_hash, g_str_equal,
59 (GDestroyNotify) NULL,
60 (GDestroyNotify) g_typelib_free);
61 repository->priv->lazy_typelibs
62 = g_hash_table_new (g_str_hash, g_str_equal);
63 repository->priv->info_by_gtype
64 = g_hash_table_new_full (g_direct_hash, g_direct_equal,
65 (GDestroyNotify) NULL,
66 (GDestroyNotify) g_base_info_unref);
70 g_irepository_finalize (GObject *object)
72 GIRepository *repository = G_IREPOSITORY (object);
74 g_hash_table_destroy (repository->priv->typelibs);
75 g_hash_table_destroy (repository->priv->lazy_typelibs);
76 g_hash_table_destroy (repository->priv->info_by_gtype);
78 (* G_OBJECT_CLASS (g_irepository_parent_class)->finalize) (G_OBJECT (repository));
82 g_irepository_class_init (GIRepositoryClass *class)
84 GObjectClass *gobject_class;
86 gobject_class = G_OBJECT_CLASS (class);
88 gobject_class->finalize = g_irepository_finalize;
90 g_type_class_add_private (class, sizeof (GIRepositoryPrivate));
96 g_static_mutex_lock (&globals_lock);
98 if (default_repository == NULL)
100 default_repository = g_object_new (G_TYPE_IREPOSITORY, NULL);
103 if (search_path == NULL)
107 const gchar *type_lib_path_env;
109 /* This variable is intended to take precedence over both the default
110 * search path, as well as anything written into code with g_irepository_prepend_search_path.
112 type_lib_path_env = g_getenv ("GI_TYPELIB_PATH");
115 override_search_path = NULL;
116 if (type_lib_path_env)
121 custom_dirs = g_strsplit (type_lib_path_env, G_SEARCHPATH_SEPARATOR_S, 0);
126 override_search_path = g_slist_prepend (override_search_path, *d);
130 /* ownership of the array content was passed to the list */
131 g_free (custom_dirs);
134 libdir = GOBJECT_INTROSPECTION_LIBDIR;
136 typelib_dir = g_build_filename (libdir, "girepository-1.0", NULL);
138 search_path = g_slist_prepend (search_path, typelib_dir);
140 search_path = g_slist_reverse (search_path);
143 g_static_mutex_unlock (&globals_lock);
147 g_irepository_prepend_search_path (const char *directory)
150 search_path = g_slist_prepend (search_path, g_strdup (directory));
154 * g_irepository_get_search_path:
156 * Returns the search path the GIRepository will use when looking for typelibs.
157 * The string is internal to GIRespository and should not be freed, nor should
160 * Return value: (element-type filename) (transfer none): list of strings
163 g_irepository_get_search_path (void)
170 build_search_path_with_overrides (void)
173 if (override_search_path != NULL)
175 result = g_slist_copy (override_search_path);
176 g_slist_last (result)->next = g_slist_copy (search_path);
179 result = g_slist_copy (search_path);
184 build_typelib_key (const char *name, const char *source)
186 GString *str = g_string_new (name);
187 g_string_append_c (str, '\0');
188 g_string_append (str, source);
189 return g_string_free (str, FALSE);
193 get_typelib_dependencies (GTypelib *typelib)
196 const char *dependencies_glob;
198 header = (Header *)typelib->data;
200 if (header->dependencies == 0)
203 dependencies_glob = g_typelib_get_string (typelib, header->dependencies);
204 return g_strsplit (dependencies_glob, "|", 0);
207 static GIRepository *
208 get_repository (GIRepository *repository)
212 if (repository != NULL)
215 return default_repository;
219 check_version_conflict (GTypelib *typelib,
220 const gchar *namespace,
221 const gchar *expected_version,
222 char **version_conflict)
225 const char *loaded_version;
227 if (expected_version == NULL)
229 if (version_conflict)
230 *version_conflict = NULL;
234 header = (Header*)typelib->data;
235 loaded_version = g_typelib_get_string (typelib, header->nsversion);
236 g_assert (loaded_version != NULL);
238 if (strcmp (expected_version, loaded_version) != 0)
240 if (version_conflict)
241 *version_conflict = (char*)loaded_version;
244 if (version_conflict)
245 *version_conflict = NULL;
250 get_registered_status (GIRepository *repository,
251 const char *namespace,
254 gboolean *lazy_status,
255 char **version_conflict)
258 repository = get_repository (repository);
260 *lazy_status = FALSE;
261 typelib = g_hash_table_lookup (repository->priv->typelibs, namespace);
263 return check_version_conflict (typelib, namespace, version, version_conflict);
264 typelib = g_hash_table_lookup (repository->priv->lazy_typelibs, namespace);
271 return check_version_conflict (typelib, namespace, version, version_conflict);
275 get_registered (GIRepository *repository,
276 const char *namespace,
279 return get_registered_status (repository, namespace, version, TRUE, NULL, NULL);
283 load_dependencies_recurse (GIRepository *repository,
289 dependencies = get_typelib_dependencies (typelib);
291 if (dependencies != NULL)
295 for (i = 0; dependencies[i]; i++)
297 char *dependency = dependencies[i];
298 const char *last_dash;
299 char *dependency_namespace;
300 const char *dependency_version;
302 last_dash = strrchr (dependency, '-');
303 dependency_namespace = g_strndup (dependency, last_dash - dependency);
304 dependency_version = last_dash+1;
306 if (!g_irepository_require (repository, dependency_namespace, dependency_version,
309 g_free (dependency_namespace);
310 g_strfreev (dependencies);
313 g_free (dependency_namespace);
315 g_strfreev (dependencies);
321 register_internal (GIRepository *repository,
328 const gchar *namespace;
329 const gchar *version;
331 g_return_val_if_fail (typelib != NULL, FALSE);
333 header = (Header *)typelib->data;
335 g_return_val_if_fail (header != NULL, FALSE);
337 namespace = g_typelib_get_string (typelib, header->namespace);
338 version = g_typelib_get_string (typelib, header->nsversion);
342 g_assert (!g_hash_table_lookup (repository->priv->lazy_typelibs,
344 g_hash_table_insert (repository->priv->lazy_typelibs,
345 build_typelib_key (namespace, source), (void *)typelib);
352 /* First, try loading all the dependencies */
353 if (!load_dependencies_recurse (repository, typelib, error))
356 /* Check if we are transitioning from lazily loaded state */
357 if (g_hash_table_lookup_extended (repository->priv->lazy_typelibs,
359 (gpointer)&key, &value))
360 g_hash_table_remove (repository->priv->lazy_typelibs, key);
362 key = build_typelib_key (namespace, source);
364 g_hash_table_insert (repository->priv->typelibs, key, (void *)typelib);
371 * g_irepository_get_dependencies:
372 * @repository: A #GIRepository, may be %NULL for the default
373 * @namespace_: Namespace of interest
375 * Return an array of all (transitive) dependencies for namespace
376 * @namespace_, including version. The returned strings are of the
377 * form <code>namespace-version</code>.
379 * Note: The namespace must have already been loaded using a function
380 * such as #g_irepository_require before calling this function.
382 * Returns: Zero-terminated string array of versioned dependencies
385 g_irepository_get_dependencies (GIRepository *repository,
386 const char *namespace)
390 g_return_val_if_fail (namespace != NULL, NULL);
392 repository = get_repository (repository);
394 typelib = get_registered (repository, namespace, NULL);
395 g_return_val_if_fail (typelib != NULL, NULL);
397 return get_typelib_dependencies (typelib);
401 g_irepository_load_typelib (GIRepository *repository,
403 GIRepositoryLoadFlags flags,
407 const char *namespace;
408 const char *nsversion;
409 gboolean allow_lazy = flags & G_IREPOSITORY_LOAD_FLAG_LAZY;
411 char *version_conflict;
413 repository = get_repository (repository);
415 header = (Header *) typelib->data;
416 namespace = g_typelib_get_string (typelib, header->namespace);
417 nsversion = g_typelib_get_string (typelib, header->nsversion);
419 if (get_registered_status (repository, namespace, nsversion, allow_lazy,
420 &is_lazy, &version_conflict))
422 if (version_conflict != NULL)
424 g_set_error (error, G_IREPOSITORY_ERROR,
425 G_IREPOSITORY_ERROR_NAMESPACE_VERSION_CONFLICT,
426 "Attempting to load namespace '%s', version '%s', but '%s' is already loaded",
427 namespace, nsversion, version_conflict);
432 return register_internal (repository, "<builtin>",
433 allow_lazy, typelib, error);
437 * g_irepository_is_registered:
438 * @repository: A #GIRepository, may be %NULL for the default
439 * @namespace_: Namespace of interest
440 * @version: (allow-none): Required version, may be %NULL for latest
442 * Check whether a particular namespace (and optionally, a specific
443 * version thereof) is currently loaded. This function is likely to
444 * only be useful in unusual circumstances; in order to act upon
445 * metadata in the namespace, you should call #g_irepository_require
446 * instead which will ensure the namespace is loaded, and return as
447 * quickly as this function will if it has already been loaded.
449 * Returns: %TRUE if namespace-version is loaded, %FALSE otherwise
452 g_irepository_is_registered (GIRepository *repository,
453 const gchar *namespace,
454 const gchar *version)
456 repository = get_repository (repository);
457 return get_registered (repository, namespace, version) != NULL;
461 * g_irepository_get_default:
463 * Returns the singleton process-global default #GIRepository. It is
464 * not currently supported to have multiple repositories in a
465 * particular process, but this function is provided in the unlikely
466 * eventuality that it would become possible, and as a convenience for
467 * higher level language bindings to conform to the GObject method
470 * All methods on #GIRepository also accept %NULL as an instance
471 * parameter to mean this default repository, which is usually more
474 * Returns: (transfer none): The global singleton #GIRepository
477 g_irepository_get_default (void)
479 return get_repository (NULL);
483 * g_irepository_get_n_infos:
484 * @repository: A #GIRepository, may be %NULL for the default
485 * @namespace_: Namespace to inspect
487 * This function returns the number of metadata entries in
488 * given namespace @namespace_. The namespace must have
489 * already been loaded before calling this function.
491 * Returns: number of metadata entries
494 g_irepository_get_n_infos (GIRepository *repository,
495 const gchar *namespace)
498 gint n_interfaces = 0;
500 g_return_val_if_fail (namespace != NULL, -1);
502 repository = get_repository (repository);
504 typelib = get_registered (repository, namespace, NULL);
506 g_return_val_if_fail (typelib != NULL, -1);
508 n_interfaces = ((Header *)typelib->data)->n_local_entries;
518 gboolean type_firstpass;
524 find_interface (gpointer key,
529 GTypelib *typelib = (GTypelib *)value;
530 Header *header = (Header *) typelib->data;
531 IfaceData *iface_data = (IfaceData *)data;
539 n_entries = ((Header *)typelib->data)->n_local_entries;
541 if (iface_data->name)
543 for (i = 1; i <= n_entries; i++)
545 entry = g_typelib_get_dir_entry (typelib, i);
546 name = g_typelib_get_string (typelib, entry->name);
547 if (strcmp (name, iface_data->name) == 0)
554 else if (iface_data->type)
556 const char *c_prefix;
557 /* Inside each typelib, we include the "C prefix" which acts as
558 * a namespace mechanism. For GtkTreeView, the C prefix is Gtk.
559 * Given the assumption that GTypes for a library also use the
560 * C prefix, we know we can skip examining a typelib if our
561 * target type does not have this typelib's C prefix.
563 * However, not every class library necessarily conforms to this,
564 * e.g. Clutter has Cogl inside it. So, we split this into two
565 * passes. First we try a lookup, skipping things which don't
566 * have the prefix. If that fails then we try a global lookup,
567 * ignoring the prefix.
569 * See http://bugzilla.gnome.org/show_bug.cgi?id=564016
571 c_prefix = g_typelib_get_string (typelib, header->c_prefix);
572 if (iface_data->type_firstpass && c_prefix != NULL)
574 if (g_ascii_strncasecmp (c_prefix, iface_data->type, strlen (c_prefix)) != 0)
578 for (i = 1; i <= n_entries; i++)
580 RegisteredTypeBlob *blob;
582 entry = g_typelib_get_dir_entry (typelib, i);
583 if (!BLOB_IS_REGISTERED_TYPE (entry))
586 blob = (RegisteredTypeBlob *)(&typelib->data[entry->offset]);
587 if (!blob->gtype_name)
590 type = g_typelib_get_string (typelib, blob->gtype_name);
591 if (strcmp (type, iface_data->type) == 0)
598 else if (iface_data->index > n_entries)
599 iface_data->index -= n_entries;
600 else if (iface_data->index > 0)
602 index = iface_data->index;
603 iface_data->index = 0;
608 entry = g_typelib_get_dir_entry (typelib, index);
609 iface_data->iface = g_info_new_full (entry->blob_type,
611 NULL, typelib, entry->offset);
616 * g_irepository_get_info:
617 * @repository: A #GIRepository, may be %NULL for the default
618 * @namespace_: Namespace to inspect
619 * @index: Offset into namespace metadata for entry
621 * This function returns a particular metadata entry in the
622 * given namespace @namespace_. The namespace must have
623 * already been loaded before calling this function.
625 * Returns: #GIBaseInfo containing metadata
628 g_irepository_get_info (GIRepository *repository,
629 const gchar *namespace,
635 g_return_val_if_fail (namespace != NULL, NULL);
637 repository = get_repository (repository);
639 data.repo = repository;
642 data.index = index + 1;
645 typelib = get_registered (repository, namespace, NULL);
647 g_return_val_if_fail (typelib != NULL, NULL);
649 find_interface ((void *)namespace, typelib, &data);
655 * g_irepository_find_by_gtype:
656 * @repository: A #GIRepository, may be %NULL for the default
657 * @gtype: GType to search for
659 * Searches all loaded namespaces for a particular #GType. Note that
660 * in order to locate the metadata, the namespace corresponding to
661 * the type must first have been loaded. There is currently no
662 * mechanism for determining the namespace which corresponds to an
663 * arbitrary GType - thus, this function will operate most reliably
664 * when you know the GType to originate from be from a loaded namespace.
666 * Returns: #GIBaseInfo representing metadata about @type, or %NULL
669 g_irepository_find_by_gtype (GIRepository *repository,
674 repository = get_repository (repository);
676 data.iface = g_hash_table_lookup (repository->priv->info_by_gtype,
680 return g_base_info_ref (data.iface);
682 data.repo = repository;
684 data.type_firstpass = TRUE;
685 data.type = g_type_name (gtype);
689 g_hash_table_foreach (repository->priv->typelibs, find_interface, &data);
690 g_hash_table_foreach (repository->priv->lazy_typelibs, find_interface, &data);
692 /* We do two passes; see comment in find_interface */
695 data.type_firstpass = FALSE;
696 g_hash_table_foreach (repository->priv->typelibs, find_interface, &data);
697 g_hash_table_foreach (repository->priv->lazy_typelibs, find_interface, &data);
701 g_hash_table_insert (repository->priv->info_by_gtype,
703 g_base_info_ref (data.iface));
709 * g_irepository_find_by_name:
710 * @repository: A #GIRepository, may be %NULL for the default
711 * @namespace_: Namespace which will be searched
712 * @name: Entry name to find
714 * Searches for a particular entry in a namespace. Before calling
715 * this function for a particular namespace, you must call
716 * #g_irepository_require once to load the namespace, or otherwise
717 * ensure the namespace has already been loaded.
719 * Returns: #GIBaseInfo representing metadata about @name, or %NULL
722 g_irepository_find_by_name (GIRepository *repository,
723 const gchar *namespace,
729 g_return_val_if_fail (namespace != NULL, NULL);
731 repository = get_repository (repository);
733 data.repo = repository;
739 typelib = get_registered (repository, namespace, NULL);
741 g_return_val_if_fail (typelib != NULL, NULL);
743 find_interface ((void *)namespace, typelib, &data);
749 collect_namespaces (gpointer key,
755 *list = g_list_append (*list, key);
759 * g_irepository_get_namespaces:
760 * @repository: A #GIRepository, may be %NULL for the default
762 * Return the list of currently loaded namespaces.
764 * Returns: (utf8) (transfer full): List of namespaces
767 g_irepository_get_loaded_namespaces (GIRepository *repository)
769 GList *l, *list = NULL;
773 repository = get_repository (repository);
775 g_hash_table_foreach (repository->priv->typelibs, collect_namespaces, &list);
776 g_hash_table_foreach (repository->priv->lazy_typelibs, collect_namespaces, &list);
778 names = g_malloc0 (sizeof (gchar *) * (g_list_length (list) + 1));
780 for (l = list; l; l = l->next)
781 names[i++] = g_strdup (l->data);
788 * g_irepository_get_version:
789 * @repository: A #GIRepository, may be %NULL for the default
790 * @namespace_: Namespace to inspect
792 * This function returns the loaded version associated with the given
793 * namespace @namespace_.
795 * Note: The namespace must have already been loaded using a function
796 * such as #g_irepository_require before calling this function.
798 * Returns: Loaded version
801 g_irepository_get_version (GIRepository *repository,
802 const gchar *namespace)
807 g_return_val_if_fail (namespace != NULL, NULL);
809 repository = get_repository (repository);
811 typelib = get_registered (repository, namespace, NULL);
813 g_return_val_if_fail (typelib != NULL, NULL);
815 header = (Header *) typelib->data;
816 return g_typelib_get_string (typelib, header->nsversion);
820 * g_irepository_get_shared_library:
821 * @repository: A #GIRepository, may be %NULL for the default
822 * @namespace_: Namespace to inspect
824 * This function returns the full path to the shared C library
825 * associated with the given namespace @namespace_. There may be no
826 * shared library path associated, in which case this function will
829 * Note: The namespace must have already been loaded using a function
830 * such as #g_irepository_require before calling this function.
832 * Returns: Full path to shared library, or %NULL if none associated
835 g_irepository_get_shared_library (GIRepository *repository,
836 const gchar *namespace)
841 g_return_val_if_fail (namespace != NULL, NULL);
843 repository = get_repository (repository);
845 typelib = get_registered (repository, namespace, NULL);
847 g_return_val_if_fail (typelib != NULL, NULL);
849 header = (Header *) typelib->data;
850 if (header->shared_library)
851 return g_typelib_get_string (typelib, header->shared_library);
857 * g_irepository_get_c_prefix
858 * @repository: A #GIRepository, may be %NULL for the default
859 * @namespace_: Namespace to inspect
861 * This function returns the "C prefix", or the C level namespace
862 * associated with the given introspection namespace. Each C symbol
863 * starts with this prefix, as well each #GType in the library.
865 * Note: The namespace must have already been loaded using a function
866 * such as #g_irepository_require before calling this function.
868 * Returns: C namespace prefix, or %NULL if none associated
871 g_irepository_get_c_prefix (GIRepository *repository,
872 const gchar *namespace_)
877 g_return_val_if_fail (namespace_ != NULL, NULL);
879 repository = get_repository (repository);
881 typelib = get_registered (repository, namespace_, NULL);
883 g_return_val_if_fail (typelib != NULL, NULL);
885 header = (Header *) typelib->data;
886 if (header->shared_library)
887 return g_typelib_get_string (typelib, header->c_prefix);
893 * g_irepository_get_typelib_path
894 * @repository: Repository, may be %NULL for the default
895 * @namespace_: GI namespace to use, e.g. "Gtk"
897 * If namespace @namespace_ is loaded, return the full path to the
898 * .typelib file it was loaded from. If the typelib for
899 * namespace @namespace_ was included in a shared library, return
900 * the special string "$lt;builtin$gt;".
902 * Returns: Filesystem path (or $lt;builtin$gt;) if successful, %NULL if namespace is not loaded
906 g_irepository_get_typelib_path (GIRepository *repository,
907 const gchar *namespace)
909 gpointer orig_key, value;
911 repository = get_repository (repository);
913 if (!g_hash_table_lookup_extended (repository->priv->typelibs, namespace,
916 if (!g_hash_table_lookup_extended (repository->priv->lazy_typelibs, namespace,
921 return ((char*)orig_key) + strlen ((char *) orig_key) + 1;
924 /* This simple search function looks for a specified namespace-version;
925 it's faster than the full directory listing required for latest version. */
927 find_namespace_version (const gchar *namespace,
928 const gchar *version,
933 GError *error = NULL;
934 GMappedFile *mfile = NULL;
937 fname = g_strdup_printf ("%s-%s.typelib", namespace, version);
939 tmp_path = build_search_path_with_overrides ();
940 for (ldir = tmp_path; ldir; ldir = ldir->next)
942 char *path = g_build_filename (ldir->data, fname, NULL);
944 mfile = g_mapped_file_new (path, FALSE, &error);
948 g_clear_error (&error);
955 g_slist_free (tmp_path);
960 parse_version (const char *version,
967 *major = strtol (version, &end, 10);
968 dot = strchr (version, '.');
976 *minor = strtol (dot+1, &end, 10);
977 if (end != (version + strlen (version)))
983 compare_version (const char *v1,
987 int v1_major, v1_minor;
988 int v2_major, v2_minor;
990 success = parse_version (v1, &v1_major, &v1_minor);
993 success = parse_version (v2, &v2_major, &v2_minor);
996 if (v1_major > v2_major)
998 else if (v2_major > v1_major)
1000 else if (v1_minor > v2_minor)
1002 else if (v2_minor > v1_minor)
1007 struct NamespaceVersionCandidadate
1016 compare_candidate_reverse (struct NamespaceVersionCandidadate *c1,
1017 struct NamespaceVersionCandidadate *c2)
1019 int result = compare_version (c1->version, c2->version);
1020 /* First, check the version */
1023 else if (result < 0)
1027 /* Now check the path index, which says how early in the search path
1028 * we found it. This ensures that of equal version targets, we
1029 * pick the earlier one.
1031 if (c1->path_index == c2->path_index)
1033 else if (c1->path_index > c2->path_index)
1041 free_candidate (struct NamespaceVersionCandidadate *candidate)
1043 g_mapped_file_unref (candidate->mfile);
1044 g_free (candidate->path);
1045 g_free (candidate->version);
1046 g_slice_free (struct NamespaceVersionCandidadate, candidate);
1049 static GMappedFile *
1050 find_namespace_latest (const gchar *namespace,
1051 gchar **version_ret,
1056 GError *error = NULL;
1057 char *namespace_dash;
1058 char *namespace_typelib;
1059 GSList *candidates = NULL;
1060 GMappedFile *result = NULL;
1063 *version_ret = NULL;
1066 namespace_dash = g_strdup_printf ("%s-", namespace);
1067 namespace_typelib = g_strdup_printf ("%s.typelib", namespace);
1070 tmp_path = build_search_path_with_overrides ();
1071 for (ldir = tmp_path; ldir; ldir = ldir->next)
1074 const char *dirname;
1077 dirname = (const char*)ldir->data;
1078 dir = g_dir_open (dirname, 0, NULL);
1081 while ((entry = g_dir_read_name (dir)) != NULL)
1084 char *path, *version;
1085 struct NamespaceVersionCandidadate *candidate;
1087 if (!g_str_has_suffix (entry, ".typelib"))
1090 if (g_str_has_prefix (entry, namespace_dash))
1092 const char *last_dash;
1093 const char *name_end;
1096 name_end = strrchr (entry, '.');
1097 last_dash = strrchr (entry, '-');
1098 version = g_strndup (last_dash+1, name_end-(last_dash+1));
1099 if (!parse_version (version, &major, &minor))
1105 path = g_build_filename (dirname, entry, NULL);
1106 mfile = g_mapped_file_new (path, FALSE, &error);
1111 g_clear_error (&error);
1114 candidate = g_slice_new0 (struct NamespaceVersionCandidadate);
1115 candidate->mfile = mfile;
1116 candidate->path_index = index;
1117 candidate->path = path;
1118 candidate->version = version;
1119 candidates = g_slist_prepend (candidates, candidate);
1125 if (candidates != NULL)
1127 struct NamespaceVersionCandidadate *elected;
1128 candidates = g_slist_sort (candidates, (GCompareFunc) compare_candidate_reverse);
1130 elected = (struct NamespaceVersionCandidadate *) candidates->data;
1131 /* Remove the elected one so we don't try to free its contents */
1132 candidates = g_slist_delete_link (candidates, candidates);
1134 result = elected->mfile;
1135 *path_ret = elected->path;
1136 *version_ret = elected->version;
1137 g_slice_free (struct NamespaceVersionCandidadate, elected); /* just free the container */
1138 g_slist_foreach (candidates, (GFunc) free_candidate, NULL);
1139 g_slist_free (candidates);
1141 g_free (namespace_dash);
1142 g_free (namespace_typelib);
1143 g_slist_free (tmp_path);
1148 * g_irepository_require:
1149 * @repository: (allow-none): Repository, may be %NULL for the default
1150 * @namespace_: GI namespace to use, e.g. "Gtk"
1151 * @version: (allow-none): Version of namespace, may be %NULL for latest
1152 * @flags: Set of %GIRepositoryLoadFlags, may be 0
1153 * @error: a #GError.
1155 * Force the namespace @namespace_ to be loaded if it isn't already.
1156 * If @namespace_ is not loaded, this function will search for a
1157 * ".typelib" file using the repository search path. In addition, a
1158 * version @version of namespace may be specified. If @version is
1159 * not specified, the latest will be used.
1161 * Returns: a pointer to the #GTypelib if successful, %NULL otherwise
1164 g_irepository_require (GIRepository *repository,
1165 const gchar *namespace,
1166 const gchar *version,
1167 GIRepositoryLoadFlags flags,
1171 GTypelib *ret = NULL;
1173 GTypelib *typelib = NULL;
1174 const gchar *typelib_namespace, *typelib_version;
1175 gboolean allow_lazy = (flags & G_IREPOSITORY_LOAD_FLAG_LAZY) > 0;
1177 char *version_conflict = NULL;
1179 char *tmp_version = NULL;
1181 g_return_val_if_fail (namespace != NULL, FALSE);
1183 repository = get_repository (repository);
1185 typelib = get_registered_status (repository, namespace, version, allow_lazy,
1186 &is_lazy, &version_conflict);
1190 if (version_conflict != NULL)
1192 g_set_error (error, G_IREPOSITORY_ERROR,
1193 G_IREPOSITORY_ERROR_NAMESPACE_VERSION_CONFLICT,
1194 "Requiring namespace '%s' version '%s', but '%s' is already loaded",
1195 namespace, version, version_conflict);
1199 if (version != NULL)
1201 mfile = find_namespace_version (namespace, version, &path);
1202 tmp_version = g_strdup (version);
1206 mfile = find_namespace_latest (namespace, &tmp_version, &path);
1211 if (version != NULL)
1212 g_set_error (error, G_IREPOSITORY_ERROR,
1213 G_IREPOSITORY_ERROR_TYPELIB_NOT_FOUND,
1214 "Typelib file for namespace '%s', version '%s' not found",
1215 namespace, version);
1217 g_set_error (error, G_IREPOSITORY_ERROR,
1218 G_IREPOSITORY_ERROR_TYPELIB_NOT_FOUND,
1219 "Typelib file for namespace '%s' (any version) not found",
1224 typelib = g_typelib_new_from_mapped_file (mfile);
1225 header = (Header *) typelib->data;
1226 typelib_namespace = g_typelib_get_string (typelib, header->namespace);
1227 typelib_version = g_typelib_get_string (typelib, header->nsversion);
1229 if (strcmp (typelib_namespace, namespace) != 0)
1231 g_set_error (error, G_IREPOSITORY_ERROR,
1232 G_IREPOSITORY_ERROR_NAMESPACE_MISMATCH,
1233 "Typelib file %s for namespace '%s' contains "
1234 "namespace '%s' which doesn't match the file name",
1235 path, namespace, typelib_namespace);
1238 if (version != NULL && strcmp (typelib_version, version) != 0)
1240 g_set_error (error, G_IREPOSITORY_ERROR,
1241 G_IREPOSITORY_ERROR_NAMESPACE_MISMATCH,
1242 "Typelib file %s for namespace '%s' contains "
1243 "version '%s' which doesn't match the expected version '%s'",
1244 path, namespace, typelib_version, version);
1248 if (!register_internal (repository, path, allow_lazy,
1251 g_typelib_free (typelib);
1256 g_free (tmp_version);
1262 g_irepository_introspect_cb (const char *option_name,
1267 gboolean ret = g_irepository_dump (value, error);
1271 static const GOptionEntry introspection_args[] = {
1272 { "introspect-dump", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_CALLBACK,
1273 g_irepository_introspect_cb, "Dump introspection information",
1274 "infile.txt,outfile.xml" },
1279 g_irepository_get_option_group (void)
1281 GOptionGroup *group;
1282 group = g_option_group_new ("girepository", "Introspection Options", "Show Introspection Options", NULL, NULL);
1284 g_option_group_add_entries (group, introspection_args);
1289 g_irepository_error_quark (void)
1291 static GQuark quark = 0;
1293 quark = g_quark_from_static_string ("g-irepository-error-quark");
1298 g_type_tag_to_string (GITypeTag type)
1302 case GI_TYPE_TAG_VOID:
1304 case GI_TYPE_TAG_BOOLEAN:
1306 case GI_TYPE_TAG_INT8:
1308 case GI_TYPE_TAG_UINT8:
1310 case GI_TYPE_TAG_INT16:
1312 case GI_TYPE_TAG_UINT16:
1314 case GI_TYPE_TAG_INT32:
1316 case GI_TYPE_TAG_UINT32:
1318 case GI_TYPE_TAG_INT64:
1320 case GI_TYPE_TAG_UINT64:
1322 case GI_TYPE_TAG_SHORT:
1324 case GI_TYPE_TAG_USHORT:
1326 case GI_TYPE_TAG_INT:
1328 case GI_TYPE_TAG_UINT:
1330 case GI_TYPE_TAG_LONG:
1332 case GI_TYPE_TAG_ULONG:
1334 case GI_TYPE_TAG_SSIZE:
1336 case GI_TYPE_TAG_SIZE:
1338 case GI_TYPE_TAG_FLOAT:
1340 case GI_TYPE_TAG_DOUBLE:
1342 case GI_TYPE_TAG_TIME_T:
1344 case GI_TYPE_TAG_GTYPE:
1346 case GI_TYPE_TAG_UTF8:
1348 case GI_TYPE_TAG_FILENAME:
1350 case GI_TYPE_TAG_ARRAY:
1352 case GI_TYPE_TAG_INTERFACE:
1354 case GI_TYPE_TAG_GLIST:
1356 case GI_TYPE_TAG_GSLIST:
1358 case GI_TYPE_TAG_GHASH:
1360 case GI_TYPE_TAG_ERROR: