1 /* -*- Mode: C; c-file-style: "gnu"; -*- */
2 /* GObject introspection: Repository implementation
4 * Copyright (C) 2005 Matthias Clasen
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
26 #include <glib/gprintf.h>
28 #include "girepository.h"
31 static GStaticMutex globals_lock = G_STATIC_MUTEX_INIT;
32 static GIRepository *default_repository = NULL;
33 static GHashTable *default_typelib = NULL;
34 static GSList *search_path = NULL;
36 struct _GIRepositoryPrivate
38 GHashTable *typelib; /* (string) namespace -> GTypelib */
41 G_DEFINE_TYPE (GIRepository, g_irepository, G_TYPE_OBJECT);
44 g_irepository_init (GIRepository *repository)
46 repository->priv = G_TYPE_INSTANCE_GET_PRIVATE (repository, G_TYPE_IREPOSITORY,
51 g_irepository_finalize (GObject *object)
53 GIRepository *repository = G_IREPOSITORY (object);
55 g_hash_table_destroy (repository->priv->typelib);
57 (* G_OBJECT_CLASS (g_irepository_parent_class)->finalize) (G_OBJECT (repository));
61 g_irepository_class_init (GIRepositoryClass *class)
63 GObjectClass *gobject_class;
65 gobject_class = G_OBJECT_CLASS (class);
67 gobject_class->finalize = g_irepository_finalize;
69 g_type_class_add_private (class, sizeof (GIRepositoryPrivate));
75 g_static_mutex_lock (&globals_lock);
77 if (default_repository == NULL)
79 default_repository = g_object_new (G_TYPE_IREPOSITORY, NULL);
80 if (default_typelib == NULL)
81 default_typelib = g_hash_table_new_full (g_str_hash, g_str_equal,
82 (GDestroyNotify) NULL,
83 (GDestroyNotify) g_typelib_free);
84 default_repository->priv->typelib = default_typelib;
87 if (search_path == NULL)
89 const gchar *const *datadirs;
90 const gchar *const *dir;
92 datadirs = g_get_system_data_dirs ();
95 for (dir = datadirs; *dir; dir++) {
96 char *path = g_build_filename (*dir, "gitypelibs", NULL);
97 search_path = g_slist_prepend (search_path, path);
99 search_path = g_slist_reverse (search_path);
102 g_static_mutex_unlock (&globals_lock);
106 g_irepository_register (GIRepository *repository,
112 GError *error = NULL;
114 g_return_val_if_fail (typelib != NULL, NULL);
116 header = (Header *)typelib->data;
118 g_return_val_if_fail (header != NULL, NULL);
120 if (repository != NULL)
122 if (repository->priv->typelib == NULL)
123 repository->priv->typelib = g_hash_table_new_full (g_str_hash, g_str_equal,
124 (GDestroyNotify) NULL,
125 (GDestroyNotify) g_typelib_free);
126 table = repository->priv->typelib;
131 table = default_typelib;
134 name = g_typelib_get_string (typelib, header->namespace);
136 if (g_hash_table_lookup (table, name))
138 g_printerr ("typelib (%p) for '%s' already registered\n",
143 g_hash_table_insert (table, g_strdup(name), (void *)typelib);
145 if (typelib->module == NULL)
146 typelib->module = g_module_open (NULL, 0);
153 g_irepository_unregister (GIRepository *repository,
154 const gchar *namespace)
158 if (repository != NULL)
159 table = repository->priv->typelib;
163 table = default_typelib;
166 if (!g_hash_table_remove (table, namespace))
168 g_printerr ("namespace '%s' not registered\n", namespace);
173 g_irepository_is_registered (GIRepository *repository,
174 const gchar *namespace)
178 if (repository != NULL)
179 table = repository->priv->typelib;
183 table = default_typelib;
186 return g_hash_table_lookup (table, namespace) != NULL;
190 g_irepository_get_default (void)
193 return default_repository;
197 count_interfaces (gpointer key,
201 guchar *typelib = ((GTypelib *) value)->data;
202 gint *n_interfaces = (gint *)data;
204 *n_interfaces += ((Header *)typelib)->n_local_entries;
208 g_irepository_get_n_infos (GIRepository *repository,
209 const gchar *namespace)
211 gint n_interfaces = 0;
217 typelib = g_hash_table_lookup (repository->priv->typelib, namespace);
220 n_interfaces = ((Header *)typelib->data)->n_local_entries;
224 g_hash_table_foreach (repository->priv->typelib,
225 count_interfaces, &n_interfaces);
240 find_interface (gpointer key,
245 GTypelib *typelib = (GTypelib *)value;
246 IfaceData *iface_data = (IfaceData *)data;
255 n_entries = ((Header *)typelib->data)->n_local_entries;
257 if (iface_data->name)
259 for (i = 1; i <= n_entries; i++)
261 entry = g_typelib_get_dir_entry (typelib, i);
262 name = g_typelib_get_string (typelib, entry->name);
263 if (strcmp (name, iface_data->name) == 0)
270 else if (iface_data->type)
272 for (i = 1; i <= n_entries; i++)
274 entry = g_typelib_get_dir_entry (typelib, i);
275 if (entry->blob_type < 4)
278 offset = *(guint32*)&typelib->data[entry->offset + 8];
279 type = g_typelib_get_string (typelib, offset);
280 if (strcmp (type, iface_data->type) == 0)
287 else if (iface_data->index > n_entries)
288 iface_data->index -= n_entries;
289 else if (iface_data->index > 0)
291 index = iface_data->index;
292 iface_data->index = 0;
297 entry = g_typelib_get_dir_entry (typelib, index);
298 iface_data->iface = g_info_new (entry->blob_type, NULL,
299 typelib, entry->offset);
304 g_irepository_get_info (GIRepository *repository,
305 const gchar *namespace,
312 data.index = index + 1;
319 typelib = g_hash_table_lookup (repository->priv->typelib, namespace);
322 find_interface ((void *)namespace, typelib, &data);
325 g_hash_table_foreach (repository->priv->typelib, find_interface, &data);
331 g_irepository_find_by_gtype (GIRepository *repository,
337 data.type = g_type_name (type);
341 g_hash_table_foreach (repository->priv->typelib, find_interface, &data);
347 * g_irepository_find_by_name
348 * @repository: A #GIRepository, may be %NULL for the default
349 * @namespace: Namespace to search in, may be %NULL for all
350 * @name: Name to find
352 * Searches for a particular name in one or all namespaces.
353 * See #g_irepository_require to load metadata for namespaces.
355 * Returns: #GIBaseInfo representing metadata about @name, or %NULL
358 g_irepository_find_by_name (GIRepository *repository,
359 const gchar *namespace,
373 typelib = g_hash_table_lookup (repository->priv->typelib, namespace);
376 find_interface ((void *)namespace, typelib, &data);
379 g_hash_table_foreach (repository->priv->typelib, find_interface, &data);
385 collect_namespaces (gpointer key,
391 *list = g_list_append (*list, key);
395 * g_irepository_get_namespaces
396 * @repository: A #GIRepository, may be %NULL for the default
398 * Return the list of currently known namespaces. Normally
399 * if you want a particular namespace, you should call
400 * #g_irepository_require to load it in.
402 * Returns: List of namespaces
405 g_irepository_get_namespaces (GIRepository *repository)
407 GList *l, *list = NULL;
411 g_hash_table_foreach (repository->priv->typelib, collect_namespaces, &list);
413 names = g_malloc0 (sizeof (gchar *) * (g_list_length (list) + 1));
415 for (l = list; l; l = l->next)
416 names[i++] = g_strdup (l->data);
423 g_irepository_get_shared_library (GIRepository *repository,
424 const gchar *namespace)
429 typelib = g_hash_table_lookup (repository->priv->typelib, namespace);
432 header = (Header *) typelib->data;
433 if (header->shared_library)
434 return g_typelib_get_string (typelib, header->shared_library);
440 g_irepository_build_search_path (void)
445 * g_irepository_require
446 * @repository: Repository, may be null for the default
447 * @namespace: GI namespace to use, e.g. "Gtk"
450 * Force the namespace @namespace to be loaded if it isn't
451 * already. If @namespace is not loaded, this function will
452 * search for a ".typelib" file using the repository search
455 * Returns: Namespace if successful, NULL otherwise
458 g_irepository_require (GIRepository *repository,
459 const gchar *namespace,
464 gchar *fname, *full_path;
466 GError *error1 = NULL;
467 GTypelib *typelib = NULL;
468 const gchar *typelib_namespace, *shlib_fname;
473 if (repository != NULL)
474 table = repository->priv->typelib;
478 table = default_typelib;
481 /* don't bother loading a namespace if already registered */
482 if (g_hash_table_lookup (table, namespace))
485 fname = g_strconcat (namespace, ".typelib", NULL);
487 for (ldir = search_path; ldir; ldir = ldir->next) {
489 full_path = g_build_filename (dir, fname, NULL);
490 mfile = g_mapped_file_new (full_path, FALSE, &error1);
492 g_clear_error (&error1);
497 typelib = g_typelib_new_from_mapped_file (mfile);
498 typelib_namespace = g_typelib_get_string (typelib, ((Header *) typelib->data)->namespace);
499 if (strcmp (typelib_namespace, namespace) != 0) {
500 g_set_error (error, G_IREPOSITORY_ERROR,
501 G_IREPOSITORY_ERROR_NAMESPACE_MISMATCH,
502 "Typelib file %s for namespace '%s' contains namespace '%s'"
503 " which doesn't match the file name",
504 full_path, namespace, typelib_namespace);
510 if (typelib == NULL) {
511 g_set_error (error, G_IREPOSITORY_ERROR,
512 G_IREPOSITORY_ERROR_TYPELIB_NOT_FOUND,
513 "Typelib file for namespace '%s' was not found in search"
514 " path or could not be openened", namespace);
517 /* optionally load shared library and attach it to the typelib */
518 shlib = ((Header *) typelib->data)->shared_library;
520 shlib_fname = g_typelib_get_string (typelib, shlib);
521 module = g_module_open (shlib_fname, G_MODULE_BIND_LAZY|G_MODULE_BIND_LOCAL);
522 if (module == NULL) {
523 g_set_error (error, G_IREPOSITORY_ERROR,
524 G_IREPOSITORY_ERROR_TYPELIB_NOT_FOUND,
525 "Typelib for namespace '%s' references shared library %s,"
526 " but it could not be openened (%s)",
527 namespace, shlib_fname, g_module_error ());
532 g_hash_table_remove (table, namespace);
533 return g_irepository_register (repository, typelib);
538 g_irepository_error_quark (void)
540 static GQuark quark = 0;
542 quark = g_quark_from_static_string ("g-irepository-error-quark");
547 g_type_tag_to_string (GITypeTag type)
551 case GI_TYPE_TAG_VOID:
553 case GI_TYPE_TAG_BOOLEAN:
555 case GI_TYPE_TAG_INT8:
557 case GI_TYPE_TAG_UINT8:
559 case GI_TYPE_TAG_INT16:
561 case GI_TYPE_TAG_UINT16:
563 case GI_TYPE_TAG_INT32:
565 case GI_TYPE_TAG_UINT32:
567 case GI_TYPE_TAG_INT64:
569 case GI_TYPE_TAG_UINT64:
571 case GI_TYPE_TAG_INT:
573 case GI_TYPE_TAG_UINT:
575 case GI_TYPE_TAG_LONG:
577 case GI_TYPE_TAG_ULONG:
579 case GI_TYPE_TAG_SSIZE:
581 case GI_TYPE_TAG_SIZE:
583 case GI_TYPE_TAG_FLOAT:
585 case GI_TYPE_TAG_DOUBLE:
587 case GI_TYPE_TAG_UTF8:
589 case GI_TYPE_TAG_FILENAME:
591 case GI_TYPE_TAG_ARRAY:
593 case GI_TYPE_TAG_INTERFACE:
595 case GI_TYPE_TAG_GLIST:
597 case GI_TYPE_TAG_GSLIST:
599 case GI_TYPE_TAG_GHASH:
601 case GI_TYPE_TAG_ERROR: