2012-02-03 19:42:56 +01:00
|
|
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
|
|
|
* GObject introspection: Repository implementation
|
2008-02-08 16:31:03 +01:00
|
|
|
*
|
|
|
|
* Copyright (C) 2005 Matthias Clasen
|
2008-10-12 06:51:48 +02:00
|
|
|
* Copyright (C) 2008 Colin Walters <walters@verbum.org>
|
|
|
|
* Copyright (C) 2008 Red Hat, Inc.
|
2008-02-08 16:31:03 +01:00
|
|
|
*
|
2023-10-25 18:10:10 +02:00
|
|
|
* SPDX-License-Identifier: LGPL-2.1-or-later
|
|
|
|
*
|
2008-02-08 16:31:03 +01:00
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the
|
|
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
|
|
* Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
2014-07-04 12:27:41 +02:00
|
|
|
#include "config.h"
|
|
|
|
|
2008-02-08 16:31:03 +01:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
Bug 556543 – reduce compiler warnings
2008-10-16 Tommi Komulainen <tommi.komulainen@iki.fi>
Bug 556543 – reduce compiler warnings
* girepository/ginfo.c:
* girepository/girepository.c (register_internal,
count_interfaces, find_interface, find_namespace_version,
parse_version, g_irepository_require):
* girepository/girmodule.c (g_ir_module_build_typelib):
* girepository/girnode.c (init_stats, dump_stats,
_g_irnode_init_stats, _g_irnode_dump_stats,
g_ir_node_can_have_member):
* girepository/girparser.c (firstpass_end_element_handler,
locate_gir, parse_basic, parse_type_internal, resolve_aliases,
start_alias, start_type, end_type_top, parse_include, cleanup,
post_filter):
* girepository/gtypelib.c (validate_function_blob, validate_enum_blob):
* giscanner/giscannermodule.c (directive_get_options,
type_get_child_list):
* giscanner/scannerlexer.l (parse_gtkdoc):
* giscanner/scannerparser.y (ctype_free):
* giscanner/sourcescanner.c:
* giscanner/sourcescanner.h (gi_source_scanner_parse_macros):
* tests/types/gitesttypes.c:
* tools/compiler.c (main):
* tools/generate.c (write_repository): Remove unused variables
and code, add missing includes, declarations and case
statements.
svn path=/trunk/; revision=730
2008-10-16 19:07:05 +02:00
|
|
|
#include <stdlib.h>
|
2008-02-08 16:31:03 +01:00
|
|
|
|
|
|
|
#include <glib.h>
|
|
|
|
#include <glib/gprintf.h>
|
|
|
|
#include <gmodule.h>
|
|
|
|
#include "girepository.h"
|
2010-05-31 22:44:46 +02:00
|
|
|
#include "gitypelib-internal.h"
|
2010-06-05 17:11:58 +02:00
|
|
|
#include "girepository-private.h"
|
2008-02-08 16:31:03 +01:00
|
|
|
|
2013-10-10 22:21:18 +02:00
|
|
|
/**
|
|
|
|
* SECTION:girepository
|
|
|
|
* @short_description: GObject Introspection repository manager
|
|
|
|
* @include: girepository.h
|
|
|
|
*
|
|
|
|
* #GIRepository is used to manage repositories of namespaces. Namespaces
|
|
|
|
* are represented on disk by type libraries (.typelib files).
|
2018-01-30 15:01:06 +01:00
|
|
|
*
|
|
|
|
* ### Discovery of type libraries
|
|
|
|
*
|
|
|
|
* #GIRepository will typically look for a `girepository-1.0` directory
|
|
|
|
* under the library directory used when compiling gobject-introspection.
|
|
|
|
*
|
|
|
|
* It is possible to control the search paths programmatically, using
|
2023-11-08 15:17:52 +01:00
|
|
|
* gi_repository_prepend_search_path(). It is also possible to modify
|
2018-01-30 15:01:06 +01:00
|
|
|
* the search paths by using the `GI_TYPELIB_PATH` environment variable.
|
|
|
|
* The environment variable takes precedence over the default search path
|
2023-11-08 15:17:52 +01:00
|
|
|
* and the gi_repository_prepend_search_path() calls.
|
2013-10-10 22:21:18 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
2008-02-08 16:31:03 +01:00
|
|
|
static GIRepository *default_repository = NULL;
|
2018-07-29 15:56:35 +02:00
|
|
|
static GSList *typelib_search_path = NULL;
|
2008-02-08 16:31:03 +01:00
|
|
|
|
2010-10-23 00:08:15 +02:00
|
|
|
typedef struct {
|
|
|
|
guint n_interfaces;
|
|
|
|
GIBaseInfo *interfaces[];
|
|
|
|
} GTypeInterfaceCache;
|
|
|
|
|
|
|
|
static void
|
|
|
|
gtype_interface_cache_free (gpointer data)
|
|
|
|
{
|
|
|
|
GTypeInterfaceCache *cache = data;
|
|
|
|
guint i;
|
|
|
|
|
|
|
|
for (i = 0; i < cache->n_interfaces; i++)
|
2023-11-08 15:17:52 +01:00
|
|
|
gi_base_info_unref ((GIBaseInfo*) cache->interfaces[i]);
|
2010-10-23 00:08:15 +02:00
|
|
|
g_free (cache);
|
|
|
|
}
|
|
|
|
|
2010-03-24 19:00:06 +01:00
|
|
|
struct _GIRepositoryPrivate
|
2008-02-08 16:31:03 +01:00
|
|
|
{
|
2010-08-31 22:36:06 +02:00
|
|
|
GHashTable *typelibs; /* (string) namespace -> GITypelib */
|
|
|
|
GHashTable *lazy_typelibs; /* (string) namespace-version -> GITypelib */
|
2008-12-10 18:53:09 +01:00
|
|
|
GHashTable *info_by_gtype; /* GType -> GIBaseInfo */
|
2011-05-19 23:46:36 +02:00
|
|
|
GHashTable *info_by_error_domain; /* GQuark -> GIBaseInfo */
|
2010-10-23 00:08:15 +02:00
|
|
|
GHashTable *interfaces_for_gtype; /* GType -> GTypeInterfaceCache */
|
2019-11-13 19:37:00 +01:00
|
|
|
GHashTable *unknown_gtypes; /* hashset of GType */
|
2008-02-08 16:31:03 +01:00
|
|
|
};
|
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
G_DEFINE_TYPE_WITH_CODE (GIRepository, gi_repository, G_TYPE_OBJECT, G_ADD_PRIVATE (GIRepository));
|
2008-02-08 16:31:03 +01:00
|
|
|
|
2011-09-05 17:19:39 +02:00
|
|
|
#ifdef G_PLATFORM_WIN32
|
|
|
|
|
|
|
|
#include <windows.h>
|
|
|
|
|
|
|
|
static HMODULE girepository_dll = NULL;
|
|
|
|
|
|
|
|
#ifdef DLL_EXPORT
|
|
|
|
|
2019-01-01 18:06:47 +01:00
|
|
|
BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved);
|
|
|
|
|
2011-09-05 17:19:39 +02:00
|
|
|
BOOL WINAPI
|
|
|
|
DllMain (HINSTANCE hinstDLL,
|
|
|
|
DWORD fdwReason,
|
|
|
|
LPVOID lpvReserved)
|
|
|
|
{
|
|
|
|
if (fdwReason == DLL_PROCESS_ATTACH)
|
|
|
|
girepository_dll = hinstDLL;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#undef GOBJECT_INTROSPECTION_LIBDIR
|
|
|
|
|
|
|
|
/* GOBJECT_INTROSPECTION_LIBDIR is used only in code called just once,
|
|
|
|
* so no problem leaking this
|
|
|
|
*/
|
|
|
|
#define GOBJECT_INTROSPECTION_LIBDIR \
|
|
|
|
g_build_filename (g_win32_get_package_installation_directory_of_module (girepository_dll), \
|
|
|
|
"lib", \
|
|
|
|
NULL)
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2010-03-24 19:00:06 +01:00
|
|
|
static void
|
2023-11-08 15:17:52 +01:00
|
|
|
gi_repository_init (GIRepository *repository)
|
2008-02-08 16:31:03 +01:00
|
|
|
{
|
2023-11-08 15:17:52 +01:00
|
|
|
repository->priv = gi_repository_get_instance_private (repository);
|
2010-03-24 19:00:06 +01:00
|
|
|
repository->priv->typelibs
|
2008-08-30 22:31:12 +02:00
|
|
|
= g_hash_table_new_full (g_str_hash, g_str_equal,
|
2023-11-24 00:22:01 +01:00
|
|
|
(GDestroyNotify) g_free,
|
2023-11-08 15:17:52 +01:00
|
|
|
(GDestroyNotify) gi_typelib_free);
|
2010-03-24 19:00:06 +01:00
|
|
|
repository->priv->lazy_typelibs
|
2012-02-03 17:11:59 +01:00
|
|
|
= g_hash_table_new_full (g_str_hash, g_str_equal,
|
|
|
|
(GDestroyNotify) g_free,
|
|
|
|
(GDestroyNotify) NULL);
|
2008-12-10 18:53:09 +01:00
|
|
|
repository->priv->info_by_gtype
|
|
|
|
= g_hash_table_new_full (g_direct_hash, g_direct_equal,
|
|
|
|
(GDestroyNotify) NULL,
|
2023-11-08 15:17:52 +01:00
|
|
|
(GDestroyNotify) gi_base_info_unref);
|
2011-05-19 23:46:36 +02:00
|
|
|
repository->priv->info_by_error_domain
|
|
|
|
= g_hash_table_new_full (g_direct_hash, g_direct_equal,
|
|
|
|
(GDestroyNotify) NULL,
|
2023-11-08 15:17:52 +01:00
|
|
|
(GDestroyNotify) gi_base_info_unref);
|
2010-10-23 00:08:15 +02:00
|
|
|
repository->priv->interfaces_for_gtype
|
|
|
|
= g_hash_table_new_full (g_direct_hash, g_direct_equal,
|
|
|
|
(GDestroyNotify) NULL,
|
|
|
|
(GDestroyNotify) gtype_interface_cache_free);
|
2019-11-13 19:37:00 +01:00
|
|
|
repository->priv->unknown_gtypes = g_hash_table_new (NULL, NULL);
|
2008-02-08 16:31:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2023-11-08 15:17:52 +01:00
|
|
|
gi_repository_finalize (GObject *object)
|
2008-02-08 16:31:03 +01:00
|
|
|
{
|
2023-11-08 15:17:52 +01:00
|
|
|
GIRepository *repository = GI_REPOSITORY (object);
|
2008-02-08 16:31:03 +01:00
|
|
|
|
2008-08-30 22:31:07 +02:00
|
|
|
g_hash_table_destroy (repository->priv->typelibs);
|
2008-10-12 06:51:48 +02:00
|
|
|
g_hash_table_destroy (repository->priv->lazy_typelibs);
|
2008-12-10 18:53:09 +01:00
|
|
|
g_hash_table_destroy (repository->priv->info_by_gtype);
|
2011-05-19 23:46:36 +02:00
|
|
|
g_hash_table_destroy (repository->priv->info_by_error_domain);
|
2010-10-23 00:08:15 +02:00
|
|
|
g_hash_table_destroy (repository->priv->interfaces_for_gtype);
|
2019-11-13 19:37:00 +01:00
|
|
|
g_hash_table_destroy (repository->priv->unknown_gtypes);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
(* G_OBJECT_CLASS (gi_repository_parent_class)->finalize) (G_OBJECT (repository));
|
2008-02-08 16:31:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2023-11-08 15:17:52 +01:00
|
|
|
gi_repository_class_init (GIRepositoryClass *class)
|
2008-02-08 16:31:03 +01:00
|
|
|
{
|
|
|
|
GObjectClass *gobject_class;
|
|
|
|
|
|
|
|
gobject_class = G_OBJECT_CLASS (class);
|
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
gobject_class->finalize = gi_repository_finalize;
|
2008-02-08 16:31:03 +01:00
|
|
|
}
|
|
|
|
|
2008-08-21 01:56:40 +02:00
|
|
|
static void
|
2008-11-17 01:49:58 +01:00
|
|
|
init_globals (void)
|
2008-08-21 01:56:40 +02:00
|
|
|
{
|
2012-12-17 15:50:28 +01:00
|
|
|
static gsize initialized = 0;
|
|
|
|
|
|
|
|
if (!g_once_init_enter (&initialized))
|
|
|
|
return;
|
2008-08-21 01:56:40 +02:00
|
|
|
|
2008-10-23 11:10:04 +02:00
|
|
|
if (default_repository == NULL)
|
2023-11-24 00:22:55 +01:00
|
|
|
default_repository = gi_repository_new ();
|
2008-08-21 01:56:40 +02:00
|
|
|
|
2018-07-29 15:56:35 +02:00
|
|
|
if (typelib_search_path == NULL)
|
2008-08-21 01:56:40 +02:00
|
|
|
{
|
2008-10-25 16:59:25 +02:00
|
|
|
const char *libdir;
|
|
|
|
char *typelib_dir;
|
2008-10-23 11:10:04 +02:00
|
|
|
const gchar *type_lib_path_env;
|
|
|
|
|
2013-10-10 22:21:18 +02:00
|
|
|
/* This variable is intended to take precedence over both:
|
|
|
|
* - the default search path;
|
2023-11-08 15:17:52 +01:00
|
|
|
* - all gi_repository_prepend_search_path() calls.
|
2009-01-12 22:42:58 +01:00
|
|
|
*/
|
2008-10-23 11:10:04 +02:00
|
|
|
type_lib_path_env = g_getenv ("GI_TYPELIB_PATH");
|
|
|
|
|
2018-07-29 15:56:35 +02:00
|
|
|
typelib_search_path = NULL;
|
2008-10-23 11:10:04 +02:00
|
|
|
if (type_lib_path_env)
|
|
|
|
{
|
|
|
|
gchar **custom_dirs;
|
|
|
|
gchar **d;
|
|
|
|
|
|
|
|
custom_dirs = g_strsplit (type_lib_path_env, G_SEARCHPATH_SEPARATOR_S, 0);
|
|
|
|
|
|
|
|
d = custom_dirs;
|
|
|
|
while (*d)
|
|
|
|
{
|
2018-07-29 15:56:35 +02:00
|
|
|
typelib_search_path = g_slist_prepend (typelib_search_path, *d);
|
2008-10-23 11:10:04 +02:00
|
|
|
d++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ownership of the array content was passed to the list */
|
|
|
|
g_free (custom_dirs);
|
|
|
|
}
|
|
|
|
|
2008-10-25 16:59:25 +02:00
|
|
|
libdir = GOBJECT_INTROSPECTION_LIBDIR;
|
2008-10-23 11:10:04 +02:00
|
|
|
|
2009-01-15 23:31:07 +01:00
|
|
|
typelib_dir = g_build_filename (libdir, "girepository-1.0", NULL);
|
2008-10-25 16:59:25 +02:00
|
|
|
|
2018-07-29 15:56:35 +02:00
|
|
|
typelib_search_path = g_slist_prepend (typelib_search_path, typelib_dir);
|
2008-10-23 11:10:04 +02:00
|
|
|
|
2018-07-29 15:56:35 +02:00
|
|
|
typelib_search_path = g_slist_reverse (typelib_search_path);
|
2008-08-21 01:56:40 +02:00
|
|
|
}
|
|
|
|
|
2012-12-17 15:50:28 +01:00
|
|
|
g_once_init_leave (&initialized, 1);
|
2008-08-21 01:56:40 +02:00
|
|
|
}
|
|
|
|
|
2013-10-10 22:21:18 +02:00
|
|
|
/**
|
2023-11-08 15:17:52 +01:00
|
|
|
* gi_repository_prepend_search_path:
|
2013-10-10 22:21:18 +02:00
|
|
|
* @directory: (type filename): directory name to prepend to the typelib
|
|
|
|
* search path
|
|
|
|
*
|
|
|
|
* Prepends @directory to the typelib search path.
|
2018-01-30 15:01:06 +01:00
|
|
|
*
|
2023-11-08 15:17:52 +01:00
|
|
|
* See also: gi_repository_get_search_path().
|
2013-10-10 22:21:18 +02:00
|
|
|
*/
|
2008-08-30 22:31:07 +02:00
|
|
|
void
|
2023-11-08 15:17:52 +01:00
|
|
|
gi_repository_prepend_search_path (const char *directory)
|
2008-08-30 22:31:07 +02:00
|
|
|
{
|
|
|
|
init_globals ();
|
2018-07-29 15:56:35 +02:00
|
|
|
typelib_search_path = g_slist_prepend (typelib_search_path, g_strdup (directory));
|
2008-08-30 22:31:07 +02:00
|
|
|
}
|
|
|
|
|
2008-11-12 13:40:34 +01:00
|
|
|
/**
|
2023-11-08 15:17:52 +01:00
|
|
|
* gi_repository_get_search_path:
|
2008-11-12 13:40:34 +01:00
|
|
|
*
|
2013-10-10 22:21:18 +02:00
|
|
|
* Returns the current search path #GIRepository will use when loading
|
2018-12-09 18:04:49 +01:00
|
|
|
* typelib files. The list is internal to #GIRepository and should not
|
2013-10-10 22:21:18 +02:00
|
|
|
* be freed, nor should its string elements.
|
2008-11-12 13:40:34 +01:00
|
|
|
*
|
2013-10-10 22:21:18 +02:00
|
|
|
* Returns: (element-type filename) (transfer none): #GSList of strings
|
2008-11-12 13:40:34 +01:00
|
|
|
*/
|
|
|
|
GSList *
|
2023-11-08 15:17:52 +01:00
|
|
|
gi_repository_get_search_path (void)
|
2008-11-12 13:40:34 +01:00
|
|
|
{
|
2018-07-29 15:56:35 +02:00
|
|
|
return typelib_search_path;
|
2008-11-12 13:40:34 +01:00
|
|
|
}
|
|
|
|
|
2008-08-21 05:06:13 +02:00
|
|
|
static char *
|
|
|
|
build_typelib_key (const char *name, const char *source)
|
|
|
|
{
|
|
|
|
GString *str = g_string_new (name);
|
|
|
|
g_string_append_c (str, '\0');
|
|
|
|
g_string_append (str, source);
|
|
|
|
return g_string_free (str, FALSE);
|
|
|
|
}
|
|
|
|
|
2015-01-31 23:22:16 +01:00
|
|
|
/* Note: Returns %NULL (not an empty %NULL-terminated array) if there are no
|
|
|
|
* dependencies. */
|
2008-08-30 22:31:07 +02:00
|
|
|
static char **
|
2010-08-31 22:36:06 +02:00
|
|
|
get_typelib_dependencies (GITypelib *typelib)
|
2008-02-08 16:31:03 +01:00
|
|
|
{
|
|
|
|
Header *header;
|
2008-08-30 22:31:07 +02:00
|
|
|
const char *dependencies_glob;
|
|
|
|
|
2008-08-09 14:55:32 +02:00
|
|
|
header = (Header *)typelib->data;
|
2008-02-08 16:31:03 +01:00
|
|
|
|
2008-08-30 22:31:07 +02:00
|
|
|
if (header->dependencies == 0)
|
|
|
|
return NULL;
|
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
dependencies_glob = gi_typelib_get_string (typelib, header->dependencies);
|
2008-08-30 22:31:07 +02:00
|
|
|
return g_strsplit (dependencies_glob, "|", 0);
|
|
|
|
}
|
2008-02-08 16:31:03 +01:00
|
|
|
|
2008-08-30 22:31:07 +02:00
|
|
|
static GIRepository *
|
|
|
|
get_repository (GIRepository *repository)
|
|
|
|
{
|
2008-11-17 01:49:58 +01:00
|
|
|
init_globals ();
|
|
|
|
|
2008-02-08 16:31:03 +01:00
|
|
|
if (repository != NULL)
|
2008-08-30 22:31:12 +02:00
|
|
|
return repository;
|
2008-11-17 01:49:58 +01:00
|
|
|
else
|
|
|
|
return default_repository;
|
2008-08-30 22:31:07 +02:00
|
|
|
}
|
|
|
|
|
2010-08-31 22:36:06 +02:00
|
|
|
static GITypelib *
|
|
|
|
check_version_conflict (GITypelib *typelib,
|
2008-10-12 06:51:48 +02:00
|
|
|
const gchar *namespace,
|
|
|
|
const gchar *expected_version,
|
|
|
|
char **version_conflict)
|
|
|
|
{
|
|
|
|
Header *header;
|
|
|
|
const char *loaded_version;
|
|
|
|
|
|
|
|
if (expected_version == NULL)
|
|
|
|
{
|
|
|
|
if (version_conflict)
|
|
|
|
*version_conflict = NULL;
|
|
|
|
return typelib;
|
|
|
|
}
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-10-12 06:51:48 +02:00
|
|
|
header = (Header*)typelib->data;
|
2023-11-08 15:17:52 +01:00
|
|
|
loaded_version = gi_typelib_get_string (typelib, header->nsversion);
|
2008-10-12 06:51:48 +02:00
|
|
|
g_assert (loaded_version != NULL);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-10-12 06:51:48 +02:00
|
|
|
if (strcmp (expected_version, loaded_version) != 0)
|
|
|
|
{
|
|
|
|
if (version_conflict)
|
|
|
|
*version_conflict = (char*)loaded_version;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if (version_conflict)
|
|
|
|
*version_conflict = NULL;
|
|
|
|
return typelib;
|
|
|
|
}
|
|
|
|
|
2010-08-31 22:36:06 +02:00
|
|
|
static GITypelib *
|
2008-08-30 22:31:12 +02:00
|
|
|
get_registered_status (GIRepository *repository,
|
|
|
|
const char *namespace,
|
2008-10-12 06:51:48 +02:00
|
|
|
const char *version,
|
2008-08-30 22:31:12 +02:00
|
|
|
gboolean allow_lazy,
|
2008-10-12 06:51:48 +02:00
|
|
|
gboolean *lazy_status,
|
|
|
|
char **version_conflict)
|
2008-08-30 22:31:07 +02:00
|
|
|
{
|
2010-08-31 22:36:06 +02:00
|
|
|
GITypelib *typelib;
|
2008-08-30 22:31:12 +02:00
|
|
|
repository = get_repository (repository);
|
|
|
|
if (lazy_status)
|
|
|
|
*lazy_status = FALSE;
|
|
|
|
typelib = g_hash_table_lookup (repository->priv->typelibs, namespace);
|
2010-03-24 19:00:06 +01:00
|
|
|
if (typelib)
|
2008-10-12 06:51:48 +02:00
|
|
|
return check_version_conflict (typelib, namespace, version, version_conflict);
|
2008-08-30 22:31:12 +02:00
|
|
|
typelib = g_hash_table_lookup (repository->priv->lazy_typelibs, namespace);
|
|
|
|
if (!typelib)
|
|
|
|
return NULL;
|
|
|
|
if (lazy_status)
|
|
|
|
*lazy_status = TRUE;
|
|
|
|
if (!allow_lazy)
|
|
|
|
return NULL;
|
2008-10-12 06:51:48 +02:00
|
|
|
return check_version_conflict (typelib, namespace, version, version_conflict);
|
2008-08-30 22:31:12 +02:00
|
|
|
}
|
2008-08-30 22:31:07 +02:00
|
|
|
|
2010-08-31 22:36:06 +02:00
|
|
|
static GITypelib *
|
2008-08-30 22:31:12 +02:00
|
|
|
get_registered (GIRepository *repository,
|
2008-10-12 06:51:48 +02:00
|
|
|
const char *namespace,
|
|
|
|
const char *version)
|
2008-08-30 22:31:12 +02:00
|
|
|
{
|
2008-10-12 06:51:48 +02:00
|
|
|
return get_registered_status (repository, namespace, version, TRUE, NULL, NULL);
|
2008-08-30 22:31:12 +02:00
|
|
|
}
|
2008-02-08 16:31:03 +01:00
|
|
|
|
2008-08-30 22:31:12 +02:00
|
|
|
static gboolean
|
|
|
|
load_dependencies_recurse (GIRepository *repository,
|
2010-08-31 22:36:06 +02:00
|
|
|
GITypelib *typelib,
|
2008-08-30 22:31:12 +02:00
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
char **dependencies;
|
2008-02-08 16:31:03 +01:00
|
|
|
|
2008-08-30 22:31:07 +02:00
|
|
|
dependencies = get_typelib_dependencies (typelib);
|
2008-08-30 22:31:12 +02:00
|
|
|
|
2008-08-30 22:31:07 +02:00
|
|
|
if (dependencies != NULL)
|
2008-02-08 16:31:03 +01:00
|
|
|
{
|
2008-08-30 22:31:07 +02:00
|
|
|
int i;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-08-30 22:31:07 +02:00
|
|
|
for (i = 0; dependencies[i]; i++)
|
|
|
|
{
|
|
|
|
char *dependency = dependencies[i];
|
2008-10-12 06:51:48 +02:00
|
|
|
const char *last_dash;
|
|
|
|
char *dependency_namespace;
|
|
|
|
const char *dependency_version;
|
|
|
|
|
|
|
|
last_dash = strrchr (dependency, '-');
|
|
|
|
dependency_namespace = g_strndup (dependency, last_dash - dependency);
|
|
|
|
dependency_version = last_dash+1;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
if (!gi_repository_require (repository, dependency_namespace, dependency_version,
|
2008-08-30 22:31:12 +02:00
|
|
|
0, error))
|
2008-08-30 22:31:07 +02:00
|
|
|
{
|
2008-10-12 06:51:48 +02:00
|
|
|
g_free (dependency_namespace);
|
2008-08-30 22:31:07 +02:00
|
|
|
g_strfreev (dependencies);
|
2008-08-30 22:31:12 +02:00
|
|
|
return FALSE;
|
2008-08-30 22:31:07 +02:00
|
|
|
}
|
2008-10-12 06:51:48 +02:00
|
|
|
g_free (dependency_namespace);
|
2008-08-30 22:31:07 +02:00
|
|
|
}
|
|
|
|
g_strfreev (dependencies);
|
2008-02-08 16:31:03 +01:00
|
|
|
}
|
2008-08-30 22:31:12 +02:00
|
|
|
return TRUE;
|
|
|
|
}
|
2008-10-12 06:51:48 +02:00
|
|
|
|
2008-08-30 22:31:12 +02:00
|
|
|
static const char *
|
|
|
|
register_internal (GIRepository *repository,
|
|
|
|
const char *source,
|
|
|
|
gboolean lazy,
|
2010-08-31 22:36:06 +02:00
|
|
|
GITypelib *typelib,
|
2008-08-30 22:31:12 +02:00
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
Header *header;
|
|
|
|
const gchar *namespace;
|
|
|
|
|
|
|
|
g_return_val_if_fail (typelib != NULL, FALSE);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-08-30 22:31:12 +02:00
|
|
|
header = (Header *)typelib->data;
|
|
|
|
|
|
|
|
g_return_val_if_fail (header != NULL, FALSE);
|
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
namespace = gi_typelib_get_string (typelib, header->namespace);
|
2008-08-30 22:31:12 +02:00
|
|
|
|
|
|
|
if (lazy)
|
|
|
|
{
|
2010-03-24 19:00:06 +01:00
|
|
|
g_assert (!g_hash_table_lookup (repository->priv->lazy_typelibs,
|
2008-08-30 22:31:12 +02:00
|
|
|
namespace));
|
2010-03-24 19:00:06 +01:00
|
|
|
g_hash_table_insert (repository->priv->lazy_typelibs,
|
2008-08-30 22:31:12 +02:00
|
|
|
build_typelib_key (namespace, source), (void *)typelib);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gpointer value;
|
|
|
|
char *key;
|
2008-08-30 22:31:07 +02:00
|
|
|
|
2008-08-30 22:31:12 +02:00
|
|
|
/* First, try loading all the dependencies */
|
|
|
|
if (!load_dependencies_recurse (repository, typelib, error))
|
|
|
|
return NULL;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-08-30 22:31:12 +02:00
|
|
|
/* Check if we are transitioning from lazily loaded state */
|
2010-03-24 19:00:06 +01:00
|
|
|
if (g_hash_table_lookup_extended (repository->priv->lazy_typelibs,
|
2008-08-30 22:31:12 +02:00
|
|
|
namespace,
|
|
|
|
(gpointer)&key, &value))
|
|
|
|
g_hash_table_remove (repository->priv->lazy_typelibs, key);
|
|
|
|
else
|
|
|
|
key = build_typelib_key (namespace, source);
|
|
|
|
|
2023-11-24 00:22:01 +01:00
|
|
|
g_hash_table_insert (repository->priv->typelibs,
|
|
|
|
g_steal_pointer (&key),
|
|
|
|
(void *)typelib);
|
2008-08-30 22:31:12 +02:00
|
|
|
}
|
2008-02-08 16:31:03 +01:00
|
|
|
|
2019-11-13 19:37:00 +01:00
|
|
|
/* These types might be resolved now, clear the cache */
|
|
|
|
g_hash_table_remove_all (repository->priv->unknown_gtypes);
|
|
|
|
|
2008-08-30 22:31:12 +02:00
|
|
|
return namespace;
|
2008-02-08 16:31:03 +01:00
|
|
|
}
|
|
|
|
|
2015-01-31 23:48:56 +01:00
|
|
|
/**
|
2023-11-08 15:17:52 +01:00
|
|
|
* gi_repository_get_immediate_dependencies:
|
2015-01-31 23:48:56 +01:00
|
|
|
* @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_.
|
2022-02-13 15:20:51 +01:00
|
|
|
* Returned strings are of the form `namespace-version`.
|
2015-01-31 23:48:56 +01:00
|
|
|
*
|
|
|
|
* Note: @namespace_ must have already been loaded using a function
|
2023-11-08 15:17:52 +01:00
|
|
|
* such as gi_repository_require() before calling this function.
|
2015-01-31 23:48:56 +01:00
|
|
|
*
|
|
|
|
* To get the transitive closure of dependencies for @namespace_, use
|
2023-11-08 15:17:52 +01:00
|
|
|
* gi_repository_get_dependencies().
|
2015-01-31 23:48:56 +01:00
|
|
|
*
|
|
|
|
* Returns: (transfer full): Zero-terminated string array of immediate versioned
|
|
|
|
* dependencies
|
|
|
|
*
|
2023-11-09 00:24:11 +01:00
|
|
|
* Since: 2.80
|
2015-01-31 23:48:56 +01:00
|
|
|
*/
|
|
|
|
char **
|
2023-11-08 15:17:52 +01:00
|
|
|
gi_repository_get_immediate_dependencies (GIRepository *repository,
|
2015-01-31 23:48:56 +01:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2008-10-13 18:59:09 +02:00
|
|
|
/**
|
2023-11-08 15:17:52 +01:00
|
|
|
* gi_repository_get_dependencies:
|
2013-10-10 22:21:18 +02:00
|
|
|
* @repository: (allow-none): A #GIRepository or %NULL for the singleton
|
|
|
|
* process-global default #GIRepository
|
2009-02-12 04:32:25 +01:00
|
|
|
* @namespace_: Namespace of interest
|
2008-10-13 18:59:09 +02:00
|
|
|
*
|
2022-02-13 15:20:51 +01:00
|
|
|
* Retrieves all (transitive) versioned dependencies for
|
|
|
|
* @namespace_.
|
|
|
|
*
|
|
|
|
* The strings are of the form `namespace-version`.
|
2008-10-13 18:59:09 +02:00
|
|
|
*
|
2013-10-10 22:21:18 +02:00
|
|
|
* Note: @namespace_ must have already been loaded using a function
|
2023-11-08 15:17:52 +01:00
|
|
|
* such as gi_repository_require() before calling this function.
|
2008-10-13 18:59:09 +02:00
|
|
|
*
|
2015-01-31 23:48:56 +01:00
|
|
|
* To get only the immediate dependencies for @namespace_, use
|
2023-11-08 15:17:52 +01:00
|
|
|
* gi_repository_get_immediate_dependencies().
|
2015-01-31 23:48:56 +01:00
|
|
|
*
|
2022-02-13 15:20:51 +01:00
|
|
|
* Returns: (transfer full) (array zero-terminated=1): all versioned
|
2013-10-10 22:21:18 +02:00
|
|
|
* dependencies
|
2008-10-13 18:59:09 +02:00
|
|
|
*/
|
2008-08-30 22:31:07 +02:00
|
|
|
char **
|
2023-11-08 15:17:52 +01:00
|
|
|
gi_repository_get_dependencies (GIRepository *repository,
|
2008-08-30 22:31:07 +02:00
|
|
|
const char *namespace)
|
|
|
|
{
|
2010-08-31 22:36:06 +02:00
|
|
|
GITypelib *typelib;
|
2015-01-31 23:48:56 +01:00
|
|
|
GHashTable *transitive_dependencies; /* set of owned utf8 */
|
|
|
|
GHashTableIter iter;
|
|
|
|
gchar *dependency;
|
|
|
|
GPtrArray *out; /* owned utf8 elements */
|
2008-08-30 22:31:07 +02:00
|
|
|
|
|
|
|
g_return_val_if_fail (namespace != NULL, NULL);
|
|
|
|
|
|
|
|
repository = get_repository (repository);
|
|
|
|
|
2008-10-12 06:51:48 +02:00
|
|
|
typelib = get_registered (repository, namespace, NULL);
|
2008-08-30 22:31:07 +02:00
|
|
|
g_return_val_if_fail (typelib != NULL, NULL);
|
2015-11-21 08:01:21 +01:00
|
|
|
|
|
|
|
/* Load the dependencies. */
|
2019-01-31 22:44:13 +01:00
|
|
|
transitive_dependencies = g_hash_table_new_full (g_str_hash, g_str_equal,
|
|
|
|
g_free, NULL);
|
2015-01-31 23:48:56 +01:00
|
|
|
get_typelib_dependencies_transitive (repository, typelib,
|
|
|
|
transitive_dependencies);
|
2008-08-30 22:31:07 +02:00
|
|
|
|
2015-01-31 23:48:56 +01:00
|
|
|
/* 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);
|
2015-01-31 23:22:16 +01:00
|
|
|
|
2015-01-31 23:48:56 +01:00
|
|
|
while (g_hash_table_iter_next (&iter, (gpointer) &dependency, NULL))
|
|
|
|
{
|
|
|
|
g_ptr_array_add (out, dependency);
|
|
|
|
g_hash_table_iter_steal (&iter);
|
|
|
|
}
|
|
|
|
|
2015-11-21 08:01:21 +01:00
|
|
|
g_hash_table_unref (transitive_dependencies);
|
|
|
|
|
2015-01-31 23:48:56 +01:00
|
|
|
/* Add a NULL terminator. */
|
|
|
|
g_ptr_array_add (out, NULL);
|
|
|
|
|
|
|
|
return (gchar **) g_ptr_array_free (out, FALSE);
|
2008-08-30 22:31:07 +02:00
|
|
|
}
|
|
|
|
|
2013-10-10 22:21:18 +02:00
|
|
|
/**
|
2023-11-08 15:17:52 +01:00
|
|
|
* gi_repository_load_typelib:
|
2013-10-10 22:21:18 +02:00
|
|
|
* @repository: (allow-none): A #GIRepository or %NULL for the singleton
|
|
|
|
* process-global default #GIRepository
|
|
|
|
* @typelib: TODO
|
|
|
|
* @flags: TODO
|
|
|
|
* @error: TODO
|
|
|
|
*
|
|
|
|
* TODO
|
|
|
|
*/
|
2008-08-30 22:31:07 +02:00
|
|
|
const char *
|
2023-11-08 15:17:52 +01:00
|
|
|
gi_repository_load_typelib (GIRepository *repository,
|
2010-08-31 22:36:06 +02:00
|
|
|
GITypelib *typelib,
|
2008-08-30 22:31:12 +02:00
|
|
|
GIRepositoryLoadFlags flags,
|
2008-08-30 22:31:07 +02:00
|
|
|
GError **error)
|
2008-08-21 05:06:13 +02:00
|
|
|
{
|
2008-08-30 22:31:07 +02:00
|
|
|
Header *header;
|
|
|
|
const char *namespace;
|
2008-10-12 06:51:48 +02:00
|
|
|
const char *nsversion;
|
2023-11-08 15:17:52 +01:00
|
|
|
gboolean allow_lazy = flags & GI_REPOSITORY_LOAD_FLAG_LAZY;
|
2008-08-30 22:31:12 +02:00
|
|
|
gboolean is_lazy;
|
2008-10-12 06:51:48 +02:00
|
|
|
char *version_conflict;
|
2008-08-30 22:31:07 +02:00
|
|
|
|
|
|
|
repository = get_repository (repository);
|
|
|
|
|
|
|
|
header = (Header *) typelib->data;
|
2023-11-08 15:17:52 +01:00
|
|
|
namespace = gi_typelib_get_string (typelib, header->namespace);
|
|
|
|
nsversion = gi_typelib_get_string (typelib, header->nsversion);
|
2008-08-30 22:31:07 +02:00
|
|
|
|
2010-03-24 19:00:06 +01:00
|
|
|
if (get_registered_status (repository, namespace, nsversion, allow_lazy,
|
2008-10-12 06:51:48 +02:00
|
|
|
&is_lazy, &version_conflict))
|
|
|
|
{
|
|
|
|
if (version_conflict != NULL)
|
|
|
|
{
|
2023-11-08 15:17:52 +01:00
|
|
|
g_set_error (error, GI_REPOSITORY_ERROR,
|
|
|
|
GI_REPOSITORY_ERROR_NAMESPACE_VERSION_CONFLICT,
|
2008-10-12 06:51:48 +02:00
|
|
|
"Attempting to load namespace '%s', version '%s', but '%s' is already loaded",
|
|
|
|
namespace, nsversion, version_conflict);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return namespace;
|
|
|
|
}
|
2010-03-24 19:00:06 +01:00
|
|
|
return register_internal (repository, "<builtin>",
|
2008-08-30 22:31:12 +02:00
|
|
|
allow_lazy, typelib, error);
|
2008-02-08 16:31:03 +01:00
|
|
|
}
|
|
|
|
|
2008-10-12 06:51:48 +02:00
|
|
|
/**
|
2023-11-08 15:17:52 +01:00
|
|
|
* gi_repository_is_registered:
|
2013-10-10 22:21:18 +02:00
|
|
|
* @repository: (allow-none): A #GIRepository or %NULL for the singleton
|
|
|
|
* process-global default #GIRepository
|
2009-02-12 04:32:25 +01:00
|
|
|
* @namespace_: Namespace of interest
|
|
|
|
* @version: (allow-none): Required version, may be %NULL for latest
|
2008-10-12 06:51:48 +02:00
|
|
|
*
|
|
|
|
* Check whether a particular namespace (and optionally, a specific
|
|
|
|
* version thereof) is currently loaded. This function is likely to
|
|
|
|
* only be useful in unusual circumstances; in order to act upon
|
2023-11-08 15:17:52 +01:00
|
|
|
* metadata in the namespace, you should call gi_repository_require()
|
2008-10-12 06:51:48 +02:00
|
|
|
* instead which will ensure the namespace is loaded, and return as
|
|
|
|
* quickly as this function will if it has already been loaded.
|
2010-03-24 19:00:06 +01:00
|
|
|
*
|
2008-10-12 06:51:48 +02:00
|
|
|
* Returns: %TRUE if namespace-version is loaded, %FALSE otherwise
|
|
|
|
*/
|
2008-02-08 16:31:03 +01:00
|
|
|
gboolean
|
2023-11-08 15:17:52 +01:00
|
|
|
gi_repository_is_registered (GIRepository *repository,
|
2008-10-12 06:51:48 +02:00
|
|
|
const gchar *namespace,
|
|
|
|
const gchar *version)
|
2008-02-08 16:31:03 +01:00
|
|
|
{
|
2008-08-30 22:31:07 +02:00
|
|
|
repository = get_repository (repository);
|
2008-10-12 06:51:48 +02:00
|
|
|
return get_registered (repository, namespace, version) != NULL;
|
2008-02-08 16:31:03 +01:00
|
|
|
}
|
|
|
|
|
2008-10-12 06:51:48 +02:00
|
|
|
/**
|
2023-11-08 15:17:52 +01:00
|
|
|
* gi_repository_get_default:
|
2008-10-12 06:51:48 +02:00
|
|
|
*
|
2013-10-10 22:21:18 +02:00
|
|
|
* Returns the singleton process-global default #GIRepository. It is
|
2008-10-12 06:51:48 +02:00
|
|
|
* not currently supported to have multiple repositories in a
|
|
|
|
* particular process, but this function is provided in the unlikely
|
|
|
|
* eventuality that it would become possible, and as a convenience for
|
|
|
|
* higher level language bindings to conform to the GObject method
|
|
|
|
* call conventions.
|
2013-10-10 22:21:18 +02:00
|
|
|
*
|
2008-10-12 06:51:48 +02:00
|
|
|
* All methods on #GIRepository also accept %NULL as an instance
|
|
|
|
* parameter to mean this default repository, which is usually more
|
|
|
|
* convenient for C.
|
2010-03-24 19:00:06 +01:00
|
|
|
*
|
|
|
|
* Returns: (transfer none): The global singleton #GIRepository
|
2008-10-12 06:51:48 +02:00
|
|
|
*/
|
2010-03-24 19:00:06 +01:00
|
|
|
GIRepository *
|
2023-11-08 15:17:52 +01:00
|
|
|
gi_repository_get_default (void)
|
2008-02-08 16:31:03 +01:00
|
|
|
{
|
2008-08-30 22:31:07 +02:00
|
|
|
return get_repository (NULL);
|
2008-02-08 16:31:03 +01:00
|
|
|
}
|
|
|
|
|
2023-11-24 00:22:55 +01:00
|
|
|
/**
|
|
|
|
* gi_repository_new:
|
|
|
|
*
|
|
|
|
* Create a new (non-singleton) #GIRepository.
|
|
|
|
*
|
|
|
|
* Most callers should use gi_repository_get_default() instead, as a singleton
|
|
|
|
* repository is more useful in most situations.
|
|
|
|
*
|
|
|
|
* Returns: (transfer full): a new #GIRepository
|
|
|
|
* Since: 2.80
|
|
|
|
*/
|
|
|
|
GIRepository *
|
|
|
|
gi_repository_new (void)
|
|
|
|
{
|
|
|
|
return g_object_new (GI_TYPE_REPOSITORY, NULL);
|
|
|
|
}
|
|
|
|
|
2008-10-12 06:51:48 +02:00
|
|
|
/**
|
2023-11-08 15:17:52 +01:00
|
|
|
* gi_repository_get_n_infos:
|
2013-10-10 22:21:18 +02:00
|
|
|
* @repository: (allow-none): A #GIRepository or %NULL for the singleton
|
|
|
|
* process-global default #GIRepository
|
2009-02-12 04:32:25 +01:00
|
|
|
* @namespace_: Namespace to inspect
|
2008-10-12 06:51:48 +02:00
|
|
|
*
|
|
|
|
* This function returns the number of metadata entries in
|
2009-02-12 04:32:25 +01:00
|
|
|
* given namespace @namespace_. The namespace must have
|
2008-10-12 06:51:48 +02:00
|
|
|
* already been loaded before calling this function.
|
|
|
|
*
|
|
|
|
* Returns: number of metadata entries
|
|
|
|
*/
|
2023-12-12 19:12:17 +01:00
|
|
|
guint
|
2023-11-08 15:17:52 +01:00
|
|
|
gi_repository_get_n_infos (GIRepository *repository,
|
2008-02-08 16:31:03 +01:00
|
|
|
const gchar *namespace)
|
|
|
|
{
|
2010-08-31 22:36:06 +02:00
|
|
|
GITypelib *typelib;
|
2023-12-12 19:12:17 +01:00
|
|
|
guint n_interfaces = 0;
|
2008-08-30 22:31:07 +02:00
|
|
|
|
2008-10-12 06:51:48 +02:00
|
|
|
g_return_val_if_fail (namespace != NULL, -1);
|
|
|
|
|
2008-08-30 22:31:07 +02:00
|
|
|
repository = get_repository (repository);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-10-12 06:51:48 +02:00
|
|
|
typelib = get_registered (repository, namespace, NULL);
|
2008-02-08 16:31:03 +01:00
|
|
|
|
2008-10-12 06:51:48 +02:00
|
|
|
g_return_val_if_fail (typelib != NULL, -1);
|
2008-02-08 16:31:03 +01:00
|
|
|
|
2008-10-12 06:51:48 +02:00
|
|
|
n_interfaces = ((Header *)typelib->data)->n_local_entries;
|
2008-02-08 16:31:03 +01:00
|
|
|
|
|
|
|
return n_interfaces;
|
|
|
|
}
|
|
|
|
|
2008-10-12 06:51:48 +02:00
|
|
|
/**
|
2023-11-08 15:17:52 +01:00
|
|
|
* gi_repository_get_info:
|
2013-10-10 22:21:18 +02:00
|
|
|
* @repository: (allow-none): A #GIRepository or %NULL for the singleton
|
|
|
|
* process-global default #GIRepository
|
2009-02-12 04:32:25 +01:00
|
|
|
* @namespace_: Namespace to inspect
|
2023-12-12 19:12:17 +01:00
|
|
|
* @idx: 0-based offset into namespace metadata for entry
|
2008-10-12 06:51:48 +02:00
|
|
|
*
|
|
|
|
* This function returns a particular metadata entry in the
|
2009-02-12 04:32:25 +01:00
|
|
|
* given namespace @namespace_. The namespace must have
|
2008-10-12 06:51:48 +02:00
|
|
|
* already been loaded before calling this function.
|
2023-11-08 15:17:52 +01:00
|
|
|
* See gi_repository_get_n_infos() to find the maximum number of
|
2010-10-21 20:59:42 +02:00
|
|
|
* entries.
|
2008-10-12 06:51:48 +02:00
|
|
|
*
|
2010-08-31 22:26:17 +02:00
|
|
|
* Returns: (transfer full): #GIBaseInfo containing metadata
|
2008-10-12 06:51:48 +02:00
|
|
|
*/
|
2010-03-24 19:00:06 +01:00
|
|
|
GIBaseInfo *
|
2023-11-08 15:17:52 +01:00
|
|
|
gi_repository_get_info (GIRepository *repository,
|
2008-02-08 16:31:03 +01:00
|
|
|
const gchar *namespace,
|
2023-12-12 19:12:17 +01:00
|
|
|
guint idx)
|
2008-02-08 16:31:03 +01:00
|
|
|
{
|
2010-08-31 22:36:06 +02:00
|
|
|
GITypelib *typelib;
|
2010-10-18 18:04:08 +02:00
|
|
|
DirEntry *entry;
|
2008-10-12 06:51:48 +02:00
|
|
|
|
|
|
|
g_return_val_if_fail (namespace != NULL, NULL);
|
2008-02-08 16:31:03 +01:00
|
|
|
|
2008-08-30 22:31:07 +02:00
|
|
|
repository = get_repository (repository);
|
|
|
|
|
2008-10-12 06:51:48 +02:00
|
|
|
typelib = get_registered (repository, namespace, NULL);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-10-12 06:51:48 +02:00
|
|
|
g_return_val_if_fail (typelib != NULL, NULL);
|
|
|
|
|
2023-12-12 19:12:17 +01:00
|
|
|
entry = gi_typelib_get_dir_entry (typelib, idx + 1);
|
2010-10-18 18:04:08 +02:00
|
|
|
if (entry == NULL)
|
|
|
|
return NULL;
|
2023-11-08 16:23:31 +01:00
|
|
|
return gi_info_new_full (entry->blob_type,
|
|
|
|
repository,
|
|
|
|
NULL, typelib, entry->offset);
|
2010-10-18 18:04:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
typedef struct {
|
Optimize g_irepository_find_by_gtype
When g_irepository_find_by_gtype() doesn't succeed on a simple prefix
match (the current 'fastpass' mechanism), it ends up taking a
considerable amount of CPU time, traversing the contents of all typelibs.
I imagine that the reasons to have the exhaustive search fallback are
not as strong as they used to be. For example, the case mentioned
(Clutter including Cogl) no longer seems to be true.
Also, typelibs (as generated by g-ir-scanner) now provide
comma-separated C prefix info for cases when the typelib includes
introspection info for multiple prefixes. For example, the Sugar typelib
has a c_prefix string of Sugar,EggSM,Gsm,Acme. So I imagine there are
not many remaining justified cases where the exhaustive search is needed.
With that in mind, I found two ways to optimize this function:
1. Support comma-separated C prefixes
2. Don't bother with an exhaustive search if we did find a typelib
claiming support for the prefix. For example, if we're looking for
GdkDeviceManagerXI2 (currently non-introspectable) and we already found
typelib files providing the 'Gdk' prefix that didn't offer this, lets
not bother with the exhaustive search, we aren't going to find anything.
2013-03-19 18:04:42 +01:00
|
|
|
const gchar *gtype_name;
|
2010-10-18 18:04:08 +02:00
|
|
|
GITypelib *result_typelib;
|
|
|
|
} FindByGTypeData;
|
2008-02-08 16:31:03 +01:00
|
|
|
|
Optimize g_irepository_find_by_gtype
When g_irepository_find_by_gtype() doesn't succeed on a simple prefix
match (the current 'fastpass' mechanism), it ends up taking a
considerable amount of CPU time, traversing the contents of all typelibs.
I imagine that the reasons to have the exhaustive search fallback are
not as strong as they used to be. For example, the case mentioned
(Clutter including Cogl) no longer seems to be true.
Also, typelibs (as generated by g-ir-scanner) now provide
comma-separated C prefix info for cases when the typelib includes
introspection info for multiple prefixes. For example, the Sugar typelib
has a c_prefix string of Sugar,EggSM,Gsm,Acme. So I imagine there are
not many remaining justified cases where the exhaustive search is needed.
With that in mind, I found two ways to optimize this function:
1. Support comma-separated C prefixes
2. Don't bother with an exhaustive search if we did find a typelib
claiming support for the prefix. For example, if we're looking for
GdkDeviceManagerXI2 (currently non-introspectable) and we already found
typelib files providing the 'Gdk' prefix that didn't offer this, lets
not bother with the exhaustive search, we aren't going to find anything.
2013-03-19 18:04:42 +01:00
|
|
|
static DirEntry *
|
|
|
|
find_by_gtype (GHashTable *table, FindByGTypeData *data, gboolean check_prefix)
|
2010-10-18 18:04:08 +02:00
|
|
|
{
|
Optimize g_irepository_find_by_gtype
When g_irepository_find_by_gtype() doesn't succeed on a simple prefix
match (the current 'fastpass' mechanism), it ends up taking a
considerable amount of CPU time, traversing the contents of all typelibs.
I imagine that the reasons to have the exhaustive search fallback are
not as strong as they used to be. For example, the case mentioned
(Clutter including Cogl) no longer seems to be true.
Also, typelibs (as generated by g-ir-scanner) now provide
comma-separated C prefix info for cases when the typelib includes
introspection info for multiple prefixes. For example, the Sugar typelib
has a c_prefix string of Sugar,EggSM,Gsm,Acme. So I imagine there are
not many remaining justified cases where the exhaustive search is needed.
With that in mind, I found two ways to optimize this function:
1. Support comma-separated C prefixes
2. Don't bother with an exhaustive search if we did find a typelib
claiming support for the prefix. For example, if we're looking for
GdkDeviceManagerXI2 (currently non-introspectable) and we already found
typelib files providing the 'Gdk' prefix that didn't offer this, lets
not bother with the exhaustive search, we aren't going to find anything.
2013-03-19 18:04:42 +01:00
|
|
|
GHashTableIter iter;
|
|
|
|
gpointer key, value;
|
|
|
|
DirEntry *ret;
|
2010-10-18 18:04:08 +02:00
|
|
|
|
Optimize g_irepository_find_by_gtype
When g_irepository_find_by_gtype() doesn't succeed on a simple prefix
match (the current 'fastpass' mechanism), it ends up taking a
considerable amount of CPU time, traversing the contents of all typelibs.
I imagine that the reasons to have the exhaustive search fallback are
not as strong as they used to be. For example, the case mentioned
(Clutter including Cogl) no longer seems to be true.
Also, typelibs (as generated by g-ir-scanner) now provide
comma-separated C prefix info for cases when the typelib includes
introspection info for multiple prefixes. For example, the Sugar typelib
has a c_prefix string of Sugar,EggSM,Gsm,Acme. So I imagine there are
not many remaining justified cases where the exhaustive search is needed.
With that in mind, I found two ways to optimize this function:
1. Support comma-separated C prefixes
2. Don't bother with an exhaustive search if we did find a typelib
claiming support for the prefix. For example, if we're looking for
GdkDeviceManagerXI2 (currently non-introspectable) and we already found
typelib files providing the 'Gdk' prefix that didn't offer this, lets
not bother with the exhaustive search, we aren't going to find anything.
2013-03-19 18:04:42 +01:00
|
|
|
g_hash_table_iter_init (&iter, table);
|
|
|
|
while (g_hash_table_iter_next (&iter, &key, &value))
|
|
|
|
{
|
|
|
|
GITypelib *typelib = (GITypelib*)value;
|
|
|
|
if (check_prefix)
|
|
|
|
{
|
2023-11-08 15:17:52 +01:00
|
|
|
if (!gi_typelib_matches_gtype_name_prefix (typelib, data->gtype_name))
|
Optimize g_irepository_find_by_gtype
When g_irepository_find_by_gtype() doesn't succeed on a simple prefix
match (the current 'fastpass' mechanism), it ends up taking a
considerable amount of CPU time, traversing the contents of all typelibs.
I imagine that the reasons to have the exhaustive search fallback are
not as strong as they used to be. For example, the case mentioned
(Clutter including Cogl) no longer seems to be true.
Also, typelibs (as generated by g-ir-scanner) now provide
comma-separated C prefix info for cases when the typelib includes
introspection info for multiple prefixes. For example, the Sugar typelib
has a c_prefix string of Sugar,EggSM,Gsm,Acme. So I imagine there are
not many remaining justified cases where the exhaustive search is needed.
With that in mind, I found two ways to optimize this function:
1. Support comma-separated C prefixes
2. Don't bother with an exhaustive search if we did find a typelib
claiming support for the prefix. For example, if we're looking for
GdkDeviceManagerXI2 (currently non-introspectable) and we already found
typelib files providing the 'Gdk' prefix that didn't offer this, lets
not bother with the exhaustive search, we aren't going to find anything.
2013-03-19 18:04:42 +01:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
ret = gi_typelib_get_dir_entry_by_gtype_name (typelib, data->gtype_name);
|
Optimize g_irepository_find_by_gtype
When g_irepository_find_by_gtype() doesn't succeed on a simple prefix
match (the current 'fastpass' mechanism), it ends up taking a
considerable amount of CPU time, traversing the contents of all typelibs.
I imagine that the reasons to have the exhaustive search fallback are
not as strong as they used to be. For example, the case mentioned
(Clutter including Cogl) no longer seems to be true.
Also, typelibs (as generated by g-ir-scanner) now provide
comma-separated C prefix info for cases when the typelib includes
introspection info for multiple prefixes. For example, the Sugar typelib
has a c_prefix string of Sugar,EggSM,Gsm,Acme. So I imagine there are
not many remaining justified cases where the exhaustive search is needed.
With that in mind, I found two ways to optimize this function:
1. Support comma-separated C prefixes
2. Don't bother with an exhaustive search if we did find a typelib
claiming support for the prefix. For example, if we're looking for
GdkDeviceManagerXI2 (currently non-introspectable) and we already found
typelib files providing the 'Gdk' prefix that didn't offer this, lets
not bother with the exhaustive search, we aren't going to find anything.
2013-03-19 18:04:42 +01:00
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
data->result_typelib = typelib;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
2008-02-08 16:31:03 +01:00
|
|
|
}
|
|
|
|
|
2008-10-12 06:51:48 +02:00
|
|
|
/**
|
2023-11-08 15:17:52 +01:00
|
|
|
* gi_repository_find_by_gtype:
|
2013-10-10 22:21:18 +02:00
|
|
|
* @repository: (allow-none): A #GIRepository or %NULL for the singleton
|
|
|
|
* process-global default #GIRepository
|
2009-02-12 04:32:25 +01:00
|
|
|
* @gtype: GType to search for
|
2008-10-12 06:51:48 +02:00
|
|
|
*
|
|
|
|
* Searches all loaded namespaces for a particular #GType. Note that
|
|
|
|
* in order to locate the metadata, the namespace corresponding to
|
|
|
|
* the type must first have been loaded. There is currently no
|
|
|
|
* mechanism for determining the namespace which corresponds to an
|
2009-02-13 00:42:47 +01:00
|
|
|
* arbitrary GType - thus, this function will operate most reliably
|
|
|
|
* when you know the GType to originate from be from a loaded namespace.
|
2008-10-12 06:51:48 +02:00
|
|
|
*
|
2010-08-31 22:26:17 +02:00
|
|
|
* Returns: (transfer full): #GIBaseInfo representing metadata about @type, or %NULL
|
2008-10-12 06:51:48 +02:00
|
|
|
*/
|
2010-03-24 19:00:06 +01:00
|
|
|
GIBaseInfo *
|
2023-11-08 15:17:52 +01:00
|
|
|
gi_repository_find_by_gtype (GIRepository *repository,
|
2022-01-12 00:01:08 +01:00
|
|
|
GType gtype)
|
2008-02-08 16:31:03 +01:00
|
|
|
{
|
2010-10-18 18:04:08 +02:00
|
|
|
FindByGTypeData data;
|
|
|
|
GIBaseInfo *cached;
|
Optimize g_irepository_find_by_gtype
When g_irepository_find_by_gtype() doesn't succeed on a simple prefix
match (the current 'fastpass' mechanism), it ends up taking a
considerable amount of CPU time, traversing the contents of all typelibs.
I imagine that the reasons to have the exhaustive search fallback are
not as strong as they used to be. For example, the case mentioned
(Clutter including Cogl) no longer seems to be true.
Also, typelibs (as generated by g-ir-scanner) now provide
comma-separated C prefix info for cases when the typelib includes
introspection info for multiple prefixes. For example, the Sugar typelib
has a c_prefix string of Sugar,EggSM,Gsm,Acme. So I imagine there are
not many remaining justified cases where the exhaustive search is needed.
With that in mind, I found two ways to optimize this function:
1. Support comma-separated C prefixes
2. Don't bother with an exhaustive search if we did find a typelib
claiming support for the prefix. For example, if we're looking for
GdkDeviceManagerXI2 (currently non-introspectable) and we already found
typelib files providing the 'Gdk' prefix that didn't offer this, lets
not bother with the exhaustive search, we aren't going to find anything.
2013-03-19 18:04:42 +01:00
|
|
|
DirEntry *entry;
|
2008-02-08 16:31:03 +01:00
|
|
|
|
2022-01-12 00:01:08 +01:00
|
|
|
g_return_val_if_fail (gtype != G_TYPE_INVALID, NULL);
|
|
|
|
|
2008-08-30 22:31:07 +02:00
|
|
|
repository = get_repository (repository);
|
|
|
|
|
2010-10-18 18:04:08 +02:00
|
|
|
cached = g_hash_table_lookup (repository->priv->info_by_gtype,
|
|
|
|
(gpointer)gtype);
|
2008-12-10 18:53:09 +01:00
|
|
|
|
2010-10-18 18:04:08 +02:00
|
|
|
if (cached != NULL)
|
2023-11-08 15:17:52 +01:00
|
|
|
return gi_base_info_ref (cached);
|
2008-12-10 18:53:09 +01:00
|
|
|
|
2019-11-13 19:37:00 +01:00
|
|
|
if (g_hash_table_contains (repository->priv->unknown_gtypes, (gpointer)gtype))
|
|
|
|
return NULL;
|
|
|
|
|
Optimize g_irepository_find_by_gtype
When g_irepository_find_by_gtype() doesn't succeed on a simple prefix
match (the current 'fastpass' mechanism), it ends up taking a
considerable amount of CPU time, traversing the contents of all typelibs.
I imagine that the reasons to have the exhaustive search fallback are
not as strong as they used to be. For example, the case mentioned
(Clutter including Cogl) no longer seems to be true.
Also, typelibs (as generated by g-ir-scanner) now provide
comma-separated C prefix info for cases when the typelib includes
introspection info for multiple prefixes. For example, the Sugar typelib
has a c_prefix string of Sugar,EggSM,Gsm,Acme. So I imagine there are
not many remaining justified cases where the exhaustive search is needed.
With that in mind, I found two ways to optimize this function:
1. Support comma-separated C prefixes
2. Don't bother with an exhaustive search if we did find a typelib
claiming support for the prefix. For example, if we're looking for
GdkDeviceManagerXI2 (currently non-introspectable) and we already found
typelib files providing the 'Gdk' prefix that didn't offer this, lets
not bother with the exhaustive search, we aren't going to find anything.
2013-03-19 18:04:42 +01:00
|
|
|
data.gtype_name = g_type_name (gtype);
|
2010-10-18 18:04:08 +02:00
|
|
|
data.result_typelib = NULL;
|
Optimize g_irepository_find_by_gtype
When g_irepository_find_by_gtype() doesn't succeed on a simple prefix
match (the current 'fastpass' mechanism), it ends up taking a
considerable amount of CPU time, traversing the contents of all typelibs.
I imagine that the reasons to have the exhaustive search fallback are
not as strong as they used to be. For example, the case mentioned
(Clutter including Cogl) no longer seems to be true.
Also, typelibs (as generated by g-ir-scanner) now provide
comma-separated C prefix info for cases when the typelib includes
introspection info for multiple prefixes. For example, the Sugar typelib
has a c_prefix string of Sugar,EggSM,Gsm,Acme. So I imagine there are
not many remaining justified cases where the exhaustive search is needed.
With that in mind, I found two ways to optimize this function:
1. Support comma-separated C prefixes
2. Don't bother with an exhaustive search if we did find a typelib
claiming support for the prefix. For example, if we're looking for
GdkDeviceManagerXI2 (currently non-introspectable) and we already found
typelib files providing the 'Gdk' prefix that didn't offer this, lets
not bother with the exhaustive search, we aren't going to find anything.
2013-03-19 18:04:42 +01:00
|
|
|
|
|
|
|
/* Inside each typelib, we include the "C prefix" which acts as
|
|
|
|
* a namespace mechanism. For GtkTreeView, the C prefix is Gtk.
|
|
|
|
* Given the assumption that GTypes for a library also use the
|
|
|
|
* C prefix, we know we can skip examining a typelib if our
|
|
|
|
* target type does not have this typelib's C prefix. Use this
|
|
|
|
* assumption as our first attempt at locating the DirEntry.
|
|
|
|
*/
|
|
|
|
entry = find_by_gtype (repository->priv->typelibs, &data, TRUE);
|
|
|
|
if (entry == NULL)
|
|
|
|
entry = find_by_gtype (repository->priv->lazy_typelibs, &data, TRUE);
|
2008-02-08 16:31:03 +01:00
|
|
|
|
Optimize g_irepository_find_by_gtype
When g_irepository_find_by_gtype() doesn't succeed on a simple prefix
match (the current 'fastpass' mechanism), it ends up taking a
considerable amount of CPU time, traversing the contents of all typelibs.
I imagine that the reasons to have the exhaustive search fallback are
not as strong as they used to be. For example, the case mentioned
(Clutter including Cogl) no longer seems to be true.
Also, typelibs (as generated by g-ir-scanner) now provide
comma-separated C prefix info for cases when the typelib includes
introspection info for multiple prefixes. For example, the Sugar typelib
has a c_prefix string of Sugar,EggSM,Gsm,Acme. So I imagine there are
not many remaining justified cases where the exhaustive search is needed.
With that in mind, I found two ways to optimize this function:
1. Support comma-separated C prefixes
2. Don't bother with an exhaustive search if we did find a typelib
claiming support for the prefix. For example, if we're looking for
GdkDeviceManagerXI2 (currently non-introspectable) and we already found
typelib files providing the 'Gdk' prefix that didn't offer this, lets
not bother with the exhaustive search, we aren't going to find anything.
2013-03-19 18:04:42 +01:00
|
|
|
/* Not ever class library necessarily specifies a correct c_prefix,
|
|
|
|
* so take a second pass. This time we will try a global lookup,
|
|
|
|
* ignoring prefixes.
|
|
|
|
* See http://bugzilla.gnome.org/show_bug.cgi?id=564016
|
|
|
|
*/
|
|
|
|
if (entry == NULL)
|
|
|
|
entry = find_by_gtype (repository->priv->typelibs, &data, FALSE);
|
|
|
|
if (entry == NULL)
|
|
|
|
entry = find_by_gtype (repository->priv->lazy_typelibs, &data, FALSE);
|
2009-02-13 00:42:47 +01:00
|
|
|
|
Optimize g_irepository_find_by_gtype
When g_irepository_find_by_gtype() doesn't succeed on a simple prefix
match (the current 'fastpass' mechanism), it ends up taking a
considerable amount of CPU time, traversing the contents of all typelibs.
I imagine that the reasons to have the exhaustive search fallback are
not as strong as they used to be. For example, the case mentioned
(Clutter including Cogl) no longer seems to be true.
Also, typelibs (as generated by g-ir-scanner) now provide
comma-separated C prefix info for cases when the typelib includes
introspection info for multiple prefixes. For example, the Sugar typelib
has a c_prefix string of Sugar,EggSM,Gsm,Acme. So I imagine there are
not many remaining justified cases where the exhaustive search is needed.
With that in mind, I found two ways to optimize this function:
1. Support comma-separated C prefixes
2. Don't bother with an exhaustive search if we did find a typelib
claiming support for the prefix. For example, if we're looking for
GdkDeviceManagerXI2 (currently non-introspectable) and we already found
typelib files providing the 'Gdk' prefix that didn't offer this, lets
not bother with the exhaustive search, we aren't going to find anything.
2013-03-19 18:04:42 +01:00
|
|
|
if (entry != NULL)
|
2010-10-18 18:04:08 +02:00
|
|
|
{
|
2023-11-08 16:23:31 +01:00
|
|
|
cached = gi_info_new_full (entry->blob_type,
|
|
|
|
repository,
|
|
|
|
NULL, data.result_typelib, entry->offset);
|
2010-10-18 18:04:08 +02:00
|
|
|
|
|
|
|
g_hash_table_insert (repository->priv->info_by_gtype,
|
|
|
|
(gpointer) gtype,
|
2023-11-08 15:17:52 +01:00
|
|
|
gi_base_info_ref (cached));
|
2010-10-18 18:04:08 +02:00
|
|
|
return cached;
|
|
|
|
}
|
2019-11-13 19:37:00 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
g_hash_table_add (repository->priv->unknown_gtypes, (gpointer) gtype);
|
|
|
|
return NULL;
|
|
|
|
}
|
2008-02-08 16:31:03 +01:00
|
|
|
}
|
|
|
|
|
2008-08-21 01:56:40 +02:00
|
|
|
/**
|
2023-11-08 15:17:52 +01:00
|
|
|
* gi_repository_find_by_name:
|
2013-10-10 22:21:18 +02:00
|
|
|
* @repository: (allow-none): A #GIRepository or %NULL for the singleton
|
|
|
|
* process-global default #GIRepository
|
2009-02-12 04:32:25 +01:00
|
|
|
* @namespace_: Namespace which will be searched
|
2008-10-12 06:51:48 +02:00
|
|
|
* @name: Entry name to find
|
|
|
|
*
|
|
|
|
* Searches for a particular entry in a namespace. Before calling
|
|
|
|
* this function for a particular namespace, you must call
|
2023-11-08 15:17:52 +01:00
|
|
|
* gi_repository_require() once to load the namespace, or otherwise
|
2008-10-12 06:51:48 +02:00
|
|
|
* ensure the namespace has already been loaded.
|
2008-08-21 01:56:40 +02:00
|
|
|
*
|
2010-08-31 22:26:17 +02:00
|
|
|
* Returns: (transfer full): #GIBaseInfo representing metadata about @name, or %NULL
|
2008-08-21 01:56:40 +02:00
|
|
|
*/
|
2010-03-24 19:00:06 +01:00
|
|
|
GIBaseInfo *
|
2023-11-08 15:17:52 +01:00
|
|
|
gi_repository_find_by_name (GIRepository *repository,
|
2008-02-08 16:31:03 +01:00
|
|
|
const gchar *namespace,
|
|
|
|
const gchar *name)
|
|
|
|
{
|
2010-08-31 22:36:06 +02:00
|
|
|
GITypelib *typelib;
|
2010-10-18 18:04:08 +02:00
|
|
|
DirEntry *entry;
|
2008-10-12 06:51:48 +02:00
|
|
|
|
|
|
|
g_return_val_if_fail (namespace != NULL, NULL);
|
2008-02-08 16:31:03 +01:00
|
|
|
|
2008-08-30 22:31:07 +02:00
|
|
|
repository = get_repository (repository);
|
2008-10-12 06:51:48 +02:00
|
|
|
typelib = get_registered (repository, namespace, NULL);
|
|
|
|
g_return_val_if_fail (typelib != NULL, NULL);
|
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
entry = gi_typelib_get_dir_entry_by_name (typelib, name);
|
2010-10-18 18:04:08 +02:00
|
|
|
if (entry == NULL)
|
|
|
|
return NULL;
|
2023-11-08 16:23:31 +01:00
|
|
|
return gi_info_new_full (entry->blob_type,
|
|
|
|
repository,
|
|
|
|
NULL, typelib, entry->offset);
|
2008-02-08 16:31:03 +01:00
|
|
|
}
|
|
|
|
|
2011-05-19 23:46:36 +02:00
|
|
|
typedef struct {
|
|
|
|
GIRepository *repository;
|
|
|
|
GQuark domain;
|
|
|
|
|
|
|
|
GITypelib *result_typelib;
|
|
|
|
DirEntry *result;
|
|
|
|
} FindByErrorDomainData;
|
|
|
|
|
|
|
|
static void
|
|
|
|
find_by_error_domain_foreach (gpointer key,
|
|
|
|
gpointer value,
|
|
|
|
gpointer datap)
|
|
|
|
{
|
|
|
|
GITypelib *typelib = (GITypelib*)value;
|
|
|
|
FindByErrorDomainData *data = datap;
|
|
|
|
|
|
|
|
if (data->result != NULL)
|
|
|
|
return;
|
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
data->result = gi_typelib_get_dir_entry_by_error_domain (typelib, data->domain);
|
2011-05-19 23:46:36 +02:00
|
|
|
if (data->result)
|
|
|
|
data->result_typelib = typelib;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2023-11-08 15:17:52 +01:00
|
|
|
* gi_repository_find_by_error_domain:
|
2013-10-10 22:21:18 +02:00
|
|
|
* @repository: (allow-none): A #GIRepository or %NULL for the singleton
|
|
|
|
* process-global default #GIRepository
|
2011-05-19 23:46:36 +02:00
|
|
|
* @domain: a #GError domain
|
|
|
|
*
|
|
|
|
* Searches for the enum type corresponding to the given #GError
|
|
|
|
* domain. Before calling this function for a particular namespace,
|
2023-11-08 15:17:52 +01:00
|
|
|
* you must call gi_repository_require() once to load the namespace, or
|
2011-05-19 23:46:36 +02:00
|
|
|
* otherwise ensure the namespace has already been loaded.
|
|
|
|
*
|
|
|
|
* Returns: (transfer full): #GIEnumInfo representing metadata about @domain's
|
|
|
|
* enum type, or %NULL
|
2023-11-09 00:24:11 +01:00
|
|
|
* Since: 2.80
|
2011-05-19 23:46:36 +02:00
|
|
|
*/
|
|
|
|
GIEnumInfo *
|
2023-11-08 15:17:52 +01:00
|
|
|
gi_repository_find_by_error_domain (GIRepository *repository,
|
2011-05-19 23:46:36 +02:00
|
|
|
GQuark domain)
|
|
|
|
{
|
|
|
|
FindByErrorDomainData data;
|
|
|
|
GIEnumInfo *cached;
|
|
|
|
|
|
|
|
repository = get_repository (repository);
|
|
|
|
|
|
|
|
cached = g_hash_table_lookup (repository->priv->info_by_error_domain,
|
|
|
|
GUINT_TO_POINTER (domain));
|
|
|
|
|
|
|
|
if (cached != NULL)
|
2023-11-28 18:14:30 +01:00
|
|
|
return (GIEnumInfo *) gi_base_info_ref ((GIBaseInfo *)cached);
|
2011-05-19 23:46:36 +02:00
|
|
|
|
|
|
|
data.repository = repository;
|
|
|
|
data.domain = domain;
|
|
|
|
data.result_typelib = NULL;
|
|
|
|
data.result = NULL;
|
|
|
|
|
|
|
|
g_hash_table_foreach (repository->priv->typelibs, find_by_error_domain_foreach, &data);
|
|
|
|
if (data.result == NULL)
|
|
|
|
g_hash_table_foreach (repository->priv->lazy_typelibs, find_by_error_domain_foreach, &data);
|
|
|
|
|
|
|
|
if (data.result != NULL)
|
|
|
|
{
|
2023-11-28 18:14:30 +01:00
|
|
|
cached = (GIEnumInfo *) gi_info_new_full (data.result->blob_type,
|
|
|
|
repository,
|
|
|
|
NULL, data.result_typelib, data.result->offset);
|
2011-05-19 23:46:36 +02:00
|
|
|
|
|
|
|
g_hash_table_insert (repository->priv->info_by_error_domain,
|
|
|
|
GUINT_TO_POINTER (domain),
|
2023-11-28 18:14:30 +01:00
|
|
|
gi_base_info_ref ((GIBaseInfo *) cached));
|
2011-05-19 23:46:36 +02:00
|
|
|
return cached;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-10-23 00:08:15 +02:00
|
|
|
/**
|
2023-11-08 15:17:52 +01:00
|
|
|
* gi_repository_get_object_gtype_interfaces:
|
2010-10-23 00:08:15 +02:00
|
|
|
* @repository: (nullable): a #GIRepository, or %NULL for the default repository
|
|
|
|
* @gtype: a #GType whose fundamental type is G_TYPE_OBJECT
|
2019-01-16 21:04:26 +01:00
|
|
|
* @n_interfaces_out: (out): Number of interfaces
|
|
|
|
* @interfaces_out: (out) (transfer none) (array length=n_interfaces_out): Interfaces for @gtype
|
2010-10-23 00:08:15 +02:00
|
|
|
*
|
|
|
|
* Look up the implemented interfaces for @gtype. This function
|
|
|
|
* cannot fail per se; but for a totally "unknown" #GType, it may
|
|
|
|
* return 0 implemented interfaces.
|
|
|
|
*
|
|
|
|
* The semantics of this function are designed for a dynamic binding,
|
|
|
|
* where in certain cases (such as a function which returns an
|
|
|
|
* interface which may have "hidden" implementation classes), not all
|
|
|
|
* data may be statically known, and will have to be determined from
|
|
|
|
* the #GType of the object. An example is g_file_new_for_path()
|
|
|
|
* returning a concrete class of #GLocalFile, which is a #GType we
|
|
|
|
* see at runtime, but not statically.
|
|
|
|
*
|
2023-11-09 00:24:11 +01:00
|
|
|
* Since: 2.80
|
2010-10-23 00:08:15 +02:00
|
|
|
*/
|
|
|
|
void
|
2023-11-08 15:17:52 +01:00
|
|
|
gi_repository_get_object_gtype_interfaces (GIRepository *repository,
|
2010-10-23 00:08:15 +02:00
|
|
|
GType gtype,
|
2023-12-12 19:12:17 +01:00
|
|
|
gsize *n_interfaces_out,
|
2019-06-20 09:18:13 +02:00
|
|
|
GIInterfaceInfo ***interfaces_out)
|
2010-10-23 00:08:15 +02:00
|
|
|
{
|
|
|
|
GTypeInterfaceCache *cache;
|
|
|
|
|
|
|
|
g_return_if_fail (g_type_fundamental (gtype) == G_TYPE_OBJECT);
|
|
|
|
|
|
|
|
repository = get_repository (repository);
|
|
|
|
|
|
|
|
cache = g_hash_table_lookup (repository->priv->interfaces_for_gtype,
|
|
|
|
(gpointer) gtype);
|
|
|
|
if (cache == NULL)
|
|
|
|
{
|
|
|
|
GType *interfaces;
|
|
|
|
guint n_interfaces;
|
|
|
|
guint i;
|
|
|
|
GList *interface_infos = NULL, *iter;
|
|
|
|
|
|
|
|
interfaces = g_type_interfaces (gtype, &n_interfaces);
|
|
|
|
for (i = 0; i < n_interfaces; i++)
|
|
|
|
{
|
|
|
|
GIBaseInfo *base_info;
|
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
base_info = gi_repository_find_by_gtype (repository, interfaces[i]);
|
2010-10-23 00:08:15 +02:00
|
|
|
if (base_info == NULL)
|
|
|
|
continue;
|
|
|
|
|
2023-12-12 17:16:30 +01:00
|
|
|
if (gi_base_info_get_info_type (base_info) != GI_INFO_TYPE_INTERFACE)
|
2010-10-23 00:08:15 +02:00
|
|
|
{
|
|
|
|
/* FIXME - could this really happen? */
|
2023-11-08 15:17:52 +01:00
|
|
|
gi_base_info_unref (base_info);
|
2010-10-23 00:08:15 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!g_list_find (interface_infos, base_info))
|
|
|
|
interface_infos = g_list_prepend (interface_infos, base_info);
|
|
|
|
}
|
|
|
|
|
|
|
|
cache = g_malloc (sizeof (GTypeInterfaceCache)
|
|
|
|
+ sizeof (GIBaseInfo*) * g_list_length (interface_infos));
|
|
|
|
cache->n_interfaces = g_list_length (interface_infos);
|
|
|
|
for (iter = interface_infos, i = 0; iter; iter = iter->next, i++)
|
|
|
|
cache->interfaces[i] = iter->data;
|
|
|
|
g_list_free (interface_infos);
|
|
|
|
|
|
|
|
g_hash_table_insert (repository->priv->interfaces_for_gtype, (gpointer) gtype,
|
|
|
|
cache);
|
2019-10-10 22:34:23 +02:00
|
|
|
|
|
|
|
g_free (interfaces);
|
2010-10-23 00:08:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
*n_interfaces_out = cache->n_interfaces;
|
2019-06-20 09:18:13 +02:00
|
|
|
*interfaces_out = (GIInterfaceInfo**)&cache->interfaces[0];
|
2010-10-23 00:08:15 +02:00
|
|
|
}
|
|
|
|
|
2008-02-08 16:31:03 +01:00
|
|
|
static void
|
|
|
|
collect_namespaces (gpointer key,
|
|
|
|
gpointer value,
|
|
|
|
gpointer data)
|
|
|
|
{
|
|
|
|
GList **list = data;
|
|
|
|
|
|
|
|
*list = g_list_append (*list, key);
|
|
|
|
}
|
|
|
|
|
2008-08-21 01:56:40 +02:00
|
|
|
/**
|
2023-11-08 15:17:52 +01:00
|
|
|
* gi_repository_get_loaded_namespaces:
|
2013-10-10 22:21:18 +02:00
|
|
|
* @repository: (allow-none): A #GIRepository or %NULL for the singleton
|
|
|
|
* process-global default #GIRepository
|
2008-08-21 01:56:40 +02:00
|
|
|
*
|
2008-10-12 06:51:48 +02:00
|
|
|
* Return the list of currently loaded namespaces.
|
|
|
|
*
|
2012-04-03 07:47:48 +02:00
|
|
|
* Returns: (element-type utf8) (transfer full): List of namespaces
|
2008-08-21 01:56:40 +02:00
|
|
|
*/
|
2010-03-24 19:00:06 +01:00
|
|
|
gchar **
|
2023-11-08 15:17:52 +01:00
|
|
|
gi_repository_get_loaded_namespaces (GIRepository *repository)
|
2008-02-08 16:31:03 +01:00
|
|
|
{
|
|
|
|
GList *l, *list = NULL;
|
|
|
|
gchar **names;
|
|
|
|
gint i;
|
|
|
|
|
2008-08-30 22:31:07 +02:00
|
|
|
repository = get_repository (repository);
|
|
|
|
|
|
|
|
g_hash_table_foreach (repository->priv->typelibs, collect_namespaces, &list);
|
2008-08-30 22:31:12 +02:00
|
|
|
g_hash_table_foreach (repository->priv->lazy_typelibs, collect_namespaces, &list);
|
2008-02-08 16:31:03 +01:00
|
|
|
|
|
|
|
names = g_malloc0 (sizeof (gchar *) * (g_list_length (list) + 1));
|
|
|
|
i = 0;
|
|
|
|
for (l = list; l; l = l->next)
|
2010-03-24 19:00:06 +01:00
|
|
|
names[i++] = g_strdup (l->data);
|
2008-02-08 16:31:03 +01:00
|
|
|
g_list_free (list);
|
|
|
|
|
|
|
|
return names;
|
|
|
|
}
|
|
|
|
|
2008-10-12 06:51:48 +02:00
|
|
|
/**
|
2023-11-08 15:17:52 +01:00
|
|
|
* gi_repository_get_version:
|
2013-10-10 22:21:18 +02:00
|
|
|
* @repository: (allow-none): A #GIRepository or %NULL for the singleton
|
|
|
|
* process-global default #GIRepository
|
2009-02-12 04:32:25 +01:00
|
|
|
* @namespace_: Namespace to inspect
|
2008-10-12 06:51:48 +02:00
|
|
|
*
|
|
|
|
* This function returns the loaded version associated with the given
|
2009-02-12 04:32:25 +01:00
|
|
|
* namespace @namespace_.
|
2008-10-12 06:51:48 +02:00
|
|
|
*
|
|
|
|
* Note: The namespace must have already been loaded using a function
|
2023-11-08 15:17:52 +01:00
|
|
|
* such as gi_repository_require() before calling this function.
|
2008-10-12 06:51:48 +02:00
|
|
|
*
|
|
|
|
* Returns: Loaded version
|
|
|
|
*/
|
|
|
|
const gchar *
|
2023-11-08 15:17:52 +01:00
|
|
|
gi_repository_get_version (GIRepository *repository,
|
2008-10-12 06:51:48 +02:00
|
|
|
const gchar *namespace)
|
|
|
|
{
|
2010-08-31 22:36:06 +02:00
|
|
|
GITypelib *typelib;
|
2008-10-12 06:51:48 +02:00
|
|
|
Header *header;
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
header = (Header *) typelib->data;
|
2023-11-08 15:17:52 +01:00
|
|
|
return gi_typelib_get_string (typelib, header->nsversion);
|
2008-10-12 06:51:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2023-11-08 15:17:52 +01:00
|
|
|
* gi_repository_get_shared_library:
|
2013-10-10 22:21:18 +02:00
|
|
|
* @repository: (allow-none): A #GIRepository or %NULL for the singleton
|
|
|
|
* process-global default #GIRepository
|
2009-02-12 04:32:25 +01:00
|
|
|
* @namespace_: Namespace to inspect
|
2008-10-12 06:51:48 +02:00
|
|
|
*
|
2015-02-14 20:37:43 +01:00
|
|
|
* This function returns a comma-separated list of paths to the
|
|
|
|
* shared C libraries associated with the given namespace @namespace_.
|
|
|
|
* There may be no shared library path associated, in which case this
|
|
|
|
* function will return %NULL.
|
2008-10-12 06:51:48 +02:00
|
|
|
*
|
|
|
|
* Note: The namespace must have already been loaded using a function
|
2023-11-08 15:17:52 +01:00
|
|
|
* such as gi_repository_require() before calling this function.
|
2008-10-12 06:51:48 +02:00
|
|
|
*
|
2020-05-14 17:20:25 +02:00
|
|
|
* Returns: (nullable): Comma-separated list of paths to shared libraries,
|
2015-02-14 20:37:43 +01:00
|
|
|
* or %NULL if none are associated
|
2008-10-12 06:51:48 +02:00
|
|
|
*/
|
2008-02-08 16:31:03 +01:00
|
|
|
const gchar *
|
2023-11-08 15:17:52 +01:00
|
|
|
gi_repository_get_shared_library (GIRepository *repository,
|
2008-10-12 06:51:48 +02:00
|
|
|
const gchar *namespace)
|
2008-02-08 16:31:03 +01:00
|
|
|
{
|
2010-08-31 22:36:06 +02:00
|
|
|
GITypelib *typelib;
|
2008-02-08 16:31:03 +01:00
|
|
|
Header *header;
|
|
|
|
|
2008-10-12 06:51:48 +02:00
|
|
|
g_return_val_if_fail (namespace != NULL, NULL);
|
|
|
|
|
2008-08-30 22:31:07 +02:00
|
|
|
repository = get_repository (repository);
|
|
|
|
|
2008-10-12 06:51:48 +02:00
|
|
|
typelib = get_registered (repository, namespace, NULL);
|
|
|
|
|
|
|
|
g_return_val_if_fail (typelib != NULL, NULL);
|
|
|
|
|
2008-08-09 14:55:32 +02:00
|
|
|
header = (Header *) typelib->data;
|
2008-02-08 16:31:03 +01:00
|
|
|
if (header->shared_library)
|
2023-11-08 15:17:52 +01:00
|
|
|
return gi_typelib_get_string (typelib, header->shared_library);
|
2008-02-08 16:31:03 +01:00
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2008-08-21 05:06:13 +02:00
|
|
|
/**
|
2023-11-08 15:17:52 +01:00
|
|
|
* gi_repository_get_c_prefix:
|
2013-10-10 22:21:18 +02:00
|
|
|
* @repository: (allow-none): A #GIRepository or %NULL for the singleton
|
|
|
|
* process-global default #GIRepository
|
2010-05-18 18:37:51 +02:00
|
|
|
* @namespace_: Namespace to inspect
|
2009-02-13 00:42:47 +01:00
|
|
|
*
|
|
|
|
* This function returns the "C prefix", or the C level namespace
|
|
|
|
* associated with the given introspection namespace. Each C symbol
|
|
|
|
* starts with this prefix, as well each #GType in the library.
|
|
|
|
*
|
|
|
|
* Note: The namespace must have already been loaded using a function
|
2023-11-08 15:17:52 +01:00
|
|
|
* such as gi_repository_require() before calling this function.
|
2009-02-13 00:42:47 +01:00
|
|
|
*
|
|
|
|
* Returns: C namespace prefix, or %NULL if none associated
|
|
|
|
*/
|
|
|
|
const gchar *
|
2023-11-08 15:17:52 +01:00
|
|
|
gi_repository_get_c_prefix (GIRepository *repository,
|
2009-02-13 00:42:47 +01:00
|
|
|
const gchar *namespace_)
|
|
|
|
{
|
2010-08-31 22:36:06 +02:00
|
|
|
GITypelib *typelib;
|
2009-02-13 00:42:47 +01:00
|
|
|
Header *header;
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
header = (Header *) typelib->data;
|
2011-09-21 19:13:45 +02:00
|
|
|
if (header->c_prefix)
|
2023-11-08 15:17:52 +01:00
|
|
|
return gi_typelib_get_string (typelib, header->c_prefix);
|
2009-02-13 00:42:47 +01:00
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2023-11-08 15:17:52 +01:00
|
|
|
* gi_repository_get_typelib_path:
|
2013-10-10 22:21:18 +02:00
|
|
|
* @repository: (allow-none): A #GIRepository or %NULL for the singleton
|
|
|
|
* process-global default #GIRepository
|
2009-02-12 04:32:25 +01:00
|
|
|
* @namespace_: GI namespace to use, e.g. "Gtk"
|
2008-08-21 05:06:13 +02:00
|
|
|
*
|
2009-02-12 04:32:25 +01:00
|
|
|
* If namespace @namespace_ is loaded, return the full path to the
|
2010-03-24 19:00:06 +01:00
|
|
|
* .typelib file it was loaded from. If the typelib for
|
2009-02-12 04:32:25 +01:00
|
|
|
* namespace @namespace_ was included in a shared library, return
|
2013-10-10 22:21:18 +02:00
|
|
|
* the special string "<builtin>".
|
2008-08-21 05:06:13 +02:00
|
|
|
*
|
2009-02-12 04:32:25 +01:00
|
|
|
* Returns: Filesystem path (or $lt;builtin$gt;) if successful, %NULL if namespace is not loaded
|
2008-08-21 05:06:13 +02:00
|
|
|
*/
|
|
|
|
|
2010-03-24 19:00:06 +01:00
|
|
|
const gchar *
|
2023-11-08 15:17:52 +01:00
|
|
|
gi_repository_get_typelib_path (GIRepository *repository,
|
2008-08-21 05:06:13 +02:00
|
|
|
const gchar *namespace)
|
2008-02-08 16:31:03 +01:00
|
|
|
{
|
2008-08-21 05:06:13 +02:00
|
|
|
gpointer orig_key, value;
|
|
|
|
|
2008-08-30 22:31:07 +02:00
|
|
|
repository = get_repository (repository);
|
|
|
|
|
|
|
|
if (!g_hash_table_lookup_extended (repository->priv->typelibs, namespace,
|
2008-08-21 05:06:13 +02:00
|
|
|
&orig_key, &value))
|
2008-08-30 22:31:12 +02:00
|
|
|
{
|
|
|
|
if (!g_hash_table_lookup_extended (repository->priv->lazy_typelibs, namespace,
|
|
|
|
&orig_key, &value))
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-08-30 22:31:12 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
2008-08-21 05:06:13 +02:00
|
|
|
return ((char*)orig_key) + strlen ((char *) orig_key) + 1;
|
2008-02-08 16:31:03 +01:00
|
|
|
}
|
|
|
|
|
2008-10-12 06:51:48 +02:00
|
|
|
/* This simple search function looks for a specified namespace-version;
|
|
|
|
it's faster than the full directory listing required for latest version. */
|
|
|
|
static GMappedFile *
|
|
|
|
find_namespace_version (const gchar *namespace,
|
|
|
|
const gchar *version,
|
2010-07-30 20:38:34 +02:00
|
|
|
GSList *search_path,
|
2008-10-12 06:51:48 +02:00
|
|
|
gchar **path_ret)
|
|
|
|
{
|
|
|
|
GSList *ldir;
|
|
|
|
GError *error = NULL;
|
|
|
|
GMappedFile *mfile = NULL;
|
|
|
|
char *fname;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-10-12 06:51:48 +02:00
|
|
|
fname = g_strdup_printf ("%s-%s.typelib", namespace, version);
|
|
|
|
|
2010-07-30 20:38:34 +02:00
|
|
|
for (ldir = search_path; ldir; ldir = ldir->next)
|
2008-10-12 06:51:48 +02:00
|
|
|
{
|
|
|
|
char *path = g_build_filename (ldir->data, fname, NULL);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-10-12 06:51:48 +02:00
|
|
|
mfile = g_mapped_file_new (path, FALSE, &error);
|
|
|
|
if (error)
|
|
|
|
{
|
|
|
|
g_free (path);
|
|
|
|
g_clear_error (&error);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
*path_ret = path;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
g_free (fname);
|
|
|
|
return mfile;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
parse_version (const char *version,
|
|
|
|
int *major,
|
|
|
|
int *minor)
|
|
|
|
{
|
|
|
|
const char *dot;
|
Bug 556543 – reduce compiler warnings
2008-10-16 Tommi Komulainen <tommi.komulainen@iki.fi>
Bug 556543 – reduce compiler warnings
* girepository/ginfo.c:
* girepository/girepository.c (register_internal,
count_interfaces, find_interface, find_namespace_version,
parse_version, g_irepository_require):
* girepository/girmodule.c (g_ir_module_build_typelib):
* girepository/girnode.c (init_stats, dump_stats,
_g_irnode_init_stats, _g_irnode_dump_stats,
g_ir_node_can_have_member):
* girepository/girparser.c (firstpass_end_element_handler,
locate_gir, parse_basic, parse_type_internal, resolve_aliases,
start_alias, start_type, end_type_top, parse_include, cleanup,
post_filter):
* girepository/gtypelib.c (validate_function_blob, validate_enum_blob):
* giscanner/giscannermodule.c (directive_get_options,
type_get_child_list):
* giscanner/scannerlexer.l (parse_gtkdoc):
* giscanner/scannerparser.y (ctype_free):
* giscanner/sourcescanner.c:
* giscanner/sourcescanner.h (gi_source_scanner_parse_macros):
* tests/types/gitesttypes.c:
* tools/compiler.c (main):
* tools/generate.c (write_repository): Remove unused variables
and code, add missing includes, declarations and case
statements.
svn path=/trunk/; revision=730
2008-10-16 19:07:05 +02:00
|
|
|
char *end;
|
2008-10-12 06:51:48 +02:00
|
|
|
|
|
|
|
*major = strtol (version, &end, 10);
|
|
|
|
dot = strchr (version, '.');
|
|
|
|
if (dot == NULL)
|
|
|
|
{
|
|
|
|
*minor = 0;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
if (dot != end)
|
|
|
|
return FALSE;
|
|
|
|
*minor = strtol (dot+1, &end, 10);
|
|
|
|
if (end != (version + strlen (version)))
|
|
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
compare_version (const char *v1,
|
|
|
|
const char *v2)
|
|
|
|
{
|
2008-10-12 23:03:41 +02:00
|
|
|
gboolean success;
|
2008-10-12 06:51:48 +02:00
|
|
|
int v1_major, v1_minor;
|
|
|
|
int v2_major, v2_minor;
|
|
|
|
|
2008-10-12 23:03:41 +02:00
|
|
|
success = parse_version (v1, &v1_major, &v1_minor);
|
|
|
|
g_assert (success);
|
|
|
|
|
|
|
|
success = parse_version (v2, &v2_major, &v2_minor);
|
|
|
|
g_assert (success);
|
2008-10-12 06:51:48 +02:00
|
|
|
|
2023-11-14 11:36:51 +01:00
|
|
|
/* Avoid a compiler warning about `success` being unused with G_DISABLE_ASSERT */
|
|
|
|
(void) success;
|
|
|
|
|
2008-10-12 06:51:48 +02:00
|
|
|
if (v1_major > v2_major)
|
|
|
|
return 1;
|
|
|
|
else if (v2_major > v1_major)
|
|
|
|
return -1;
|
|
|
|
else if (v1_minor > v2_minor)
|
|
|
|
return 1;
|
|
|
|
else if (v2_minor > v1_minor)
|
|
|
|
return -1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct NamespaceVersionCandidadate
|
|
|
|
{
|
|
|
|
GMappedFile *mfile;
|
2008-10-21 20:41:36 +02:00
|
|
|
int path_index;
|
2008-10-12 06:51:48 +02:00
|
|
|
char *path;
|
|
|
|
char *version;
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
compare_candidate_reverse (struct NamespaceVersionCandidadate *c1,
|
|
|
|
struct NamespaceVersionCandidadate *c2)
|
|
|
|
{
|
|
|
|
int result = compare_version (c1->version, c2->version);
|
2008-10-21 20:41:36 +02:00
|
|
|
/* First, check the version */
|
2008-10-12 06:51:48 +02:00
|
|
|
if (result > 0)
|
|
|
|
return -1;
|
|
|
|
else if (result < 0)
|
|
|
|
return 1;
|
2010-03-24 19:00:06 +01:00
|
|
|
else
|
2008-10-21 20:41:36 +02:00
|
|
|
{
|
|
|
|
/* Now check the path index, which says how early in the search path
|
|
|
|
* we found it. This ensures that of equal version targets, we
|
|
|
|
* pick the earlier one.
|
|
|
|
*/
|
|
|
|
if (c1->path_index == c2->path_index)
|
|
|
|
return 0;
|
|
|
|
else if (c1->path_index > c2->path_index)
|
|
|
|
return 1;
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
}
|
2008-10-12 06:51:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
free_candidate (struct NamespaceVersionCandidadate *candidate)
|
|
|
|
{
|
2009-12-03 21:35:23 +01:00
|
|
|
g_mapped_file_unref (candidate->mfile);
|
2008-10-12 06:51:48 +02:00
|
|
|
g_free (candidate->path);
|
|
|
|
g_free (candidate->version);
|
2010-05-20 16:33:49 +02:00
|
|
|
g_slice_free (struct NamespaceVersionCandidadate, candidate);
|
2008-10-12 06:51:48 +02:00
|
|
|
}
|
|
|
|
|
2010-07-27 13:06:54 +02:00
|
|
|
static GSList *
|
2010-07-30 20:38:34 +02:00
|
|
|
enumerate_namespace_versions (const gchar *namespace,
|
|
|
|
GSList *search_path)
|
2008-10-12 06:51:48 +02:00
|
|
|
{
|
2010-07-27 13:06:54 +02:00
|
|
|
GSList *candidates = NULL;
|
|
|
|
GHashTable *found_versions = g_hash_table_new (g_str_hash, g_str_equal);
|
|
|
|
char *namespace_dash;
|
|
|
|
char *namespace_typelib;
|
2008-10-12 06:51:48 +02:00
|
|
|
GSList *ldir;
|
|
|
|
GError *error = NULL;
|
2008-10-21 20:41:36 +02:00
|
|
|
int index;
|
2008-10-12 06:51:48 +02:00
|
|
|
|
|
|
|
namespace_dash = g_strdup_printf ("%s-", namespace);
|
|
|
|
namespace_typelib = g_strdup_printf ("%s.typelib", namespace);
|
2008-10-21 20:41:36 +02:00
|
|
|
|
|
|
|
index = 0;
|
2010-07-30 20:38:34 +02:00
|
|
|
for (ldir = search_path; ldir; ldir = ldir->next)
|
2008-10-12 06:51:48 +02:00
|
|
|
{
|
|
|
|
GDir *dir;
|
|
|
|
const char *dirname;
|
|
|
|
const char *entry;
|
|
|
|
|
|
|
|
dirname = (const char*)ldir->data;
|
|
|
|
dir = g_dir_open (dirname, 0, NULL);
|
|
|
|
if (dir == NULL)
|
|
|
|
continue;
|
2010-03-24 19:00:06 +01:00
|
|
|
while ((entry = g_dir_read_name (dir)) != NULL)
|
2008-10-12 06:51:48 +02:00
|
|
|
{
|
|
|
|
GMappedFile *mfile;
|
|
|
|
char *path, *version;
|
|
|
|
struct NamespaceVersionCandidadate *candidate;
|
|
|
|
|
|
|
|
if (!g_str_has_suffix (entry, ".typelib"))
|
|
|
|
continue;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-10-12 06:51:48 +02:00
|
|
|
if (g_str_has_prefix (entry, namespace_dash))
|
|
|
|
{
|
|
|
|
const char *last_dash;
|
|
|
|
const char *name_end;
|
|
|
|
int major, minor;
|
|
|
|
|
|
|
|
name_end = strrchr (entry, '.');
|
|
|
|
last_dash = strrchr (entry, '-');
|
|
|
|
version = g_strndup (last_dash+1, name_end-(last_dash+1));
|
|
|
|
if (!parse_version (version, &major, &minor))
|
2010-09-25 07:12:07 +02:00
|
|
|
{
|
|
|
|
g_free (version);
|
|
|
|
continue;
|
|
|
|
}
|
2008-10-12 06:51:48 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
continue;
|
|
|
|
|
2010-07-27 13:06:54 +02:00
|
|
|
if (g_hash_table_lookup (found_versions, version) != NULL)
|
2010-09-25 07:12:07 +02:00
|
|
|
{
|
|
|
|
g_free (version);
|
|
|
|
continue;
|
|
|
|
}
|
2010-07-27 13:06:54 +02:00
|
|
|
|
2008-10-12 06:51:48 +02:00
|
|
|
path = g_build_filename (dirname, entry, NULL);
|
|
|
|
mfile = g_mapped_file_new (path, FALSE, &error);
|
|
|
|
if (mfile == NULL)
|
|
|
|
{
|
|
|
|
g_free (path);
|
|
|
|
g_free (version);
|
|
|
|
g_clear_error (&error);
|
|
|
|
continue;
|
|
|
|
}
|
2010-05-20 16:33:49 +02:00
|
|
|
candidate = g_slice_new0 (struct NamespaceVersionCandidadate);
|
2008-10-12 06:51:48 +02:00
|
|
|
candidate->mfile = mfile;
|
2008-10-21 20:41:36 +02:00
|
|
|
candidate->path_index = index;
|
2008-10-12 06:51:48 +02:00
|
|
|
candidate->path = path;
|
|
|
|
candidate->version = version;
|
|
|
|
candidates = g_slist_prepend (candidates, candidate);
|
2019-01-31 22:46:38 +01:00
|
|
|
g_hash_table_add (found_versions, version);
|
2008-10-12 06:51:48 +02:00
|
|
|
}
|
|
|
|
g_dir_close (dir);
|
2008-10-21 20:41:36 +02:00
|
|
|
index++;
|
2008-10-12 06:51:48 +02:00
|
|
|
}
|
2010-07-28 13:52:05 +02:00
|
|
|
|
2010-07-27 13:06:54 +02:00
|
|
|
g_free (namespace_dash);
|
|
|
|
g_free (namespace_typelib);
|
|
|
|
g_hash_table_destroy (found_versions);
|
|
|
|
|
|
|
|
return candidates;
|
|
|
|
}
|
|
|
|
|
|
|
|
static GMappedFile *
|
|
|
|
find_namespace_latest (const gchar *namespace,
|
2010-07-30 20:38:34 +02:00
|
|
|
GSList *search_path,
|
2010-07-27 13:06:54 +02:00
|
|
|
gchar **version_ret,
|
|
|
|
gchar **path_ret)
|
|
|
|
{
|
|
|
|
GSList *candidates;
|
|
|
|
GMappedFile *result = NULL;
|
|
|
|
|
|
|
|
*version_ret = NULL;
|
|
|
|
*path_ret = NULL;
|
|
|
|
|
2010-07-30 20:38:34 +02:00
|
|
|
candidates = enumerate_namespace_versions (namespace, search_path);
|
2008-10-12 06:51:48 +02:00
|
|
|
|
|
|
|
if (candidates != NULL)
|
|
|
|
{
|
|
|
|
struct NamespaceVersionCandidadate *elected;
|
|
|
|
candidates = g_slist_sort (candidates, (GCompareFunc) compare_candidate_reverse);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-10-12 06:51:48 +02:00
|
|
|
elected = (struct NamespaceVersionCandidadate *) candidates->data;
|
2008-11-12 15:42:13 +01:00
|
|
|
/* Remove the elected one so we don't try to free its contents */
|
2008-10-12 06:51:48 +02:00
|
|
|
candidates = g_slist_delete_link (candidates, candidates);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-10-12 06:51:48 +02:00
|
|
|
result = elected->mfile;
|
|
|
|
*path_ret = elected->path;
|
|
|
|
*version_ret = elected->version;
|
2010-05-20 16:33:49 +02:00
|
|
|
g_slice_free (struct NamespaceVersionCandidadate, elected); /* just free the container */
|
2018-07-29 15:24:59 +02:00
|
|
|
g_slist_foreach (candidates, (GFunc) (void *) free_candidate, NULL);
|
2008-10-12 06:51:48 +02:00
|
|
|
g_slist_free (candidates);
|
2010-03-24 19:00:06 +01:00
|
|
|
}
|
2008-10-12 06:51:48 +02:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2010-07-27 13:06:54 +02:00
|
|
|
/**
|
2023-11-08 15:17:52 +01:00
|
|
|
* gi_repository_enumerate_versions:
|
2013-10-10 22:21:18 +02:00
|
|
|
* @repository: (allow-none): A #GIRepository or %NULL for the singleton
|
|
|
|
* process-global default #GIRepository
|
2010-07-27 13:06:54 +02:00
|
|
|
* @namespace_: GI namespace, e.g. "Gtk"
|
|
|
|
*
|
2010-08-16 22:39:19 +02:00
|
|
|
* Obtain an unordered list of versions (either currently loaded or
|
|
|
|
* available) for @namespace_ in this @repository.
|
2010-07-28 13:52:05 +02:00
|
|
|
*
|
|
|
|
* Returns: (element-type utf8) (transfer full): the array of versions.
|
2010-07-27 13:06:54 +02:00
|
|
|
*/
|
|
|
|
GList *
|
2023-11-08 15:17:52 +01:00
|
|
|
gi_repository_enumerate_versions (GIRepository *repository,
|
2018-01-30 15:01:06 +01:00
|
|
|
const gchar *namespace_)
|
2010-07-27 13:06:54 +02:00
|
|
|
{
|
|
|
|
GList *ret = NULL;
|
|
|
|
GSList *candidates, *link;
|
2010-08-16 22:39:19 +02:00
|
|
|
const gchar *loaded_version;
|
2010-07-28 13:52:05 +02:00
|
|
|
|
2016-04-28 16:22:38 +02:00
|
|
|
init_globals ();
|
2018-07-29 15:56:35 +02:00
|
|
|
candidates = enumerate_namespace_versions (namespace_, typelib_search_path);
|
2010-07-30 20:38:34 +02:00
|
|
|
|
2010-07-27 13:06:54 +02:00
|
|
|
for (link = candidates; link; link = link->next)
|
|
|
|
{
|
|
|
|
struct NamespaceVersionCandidadate *candidate = link->data;
|
2010-08-16 22:39:19 +02:00
|
|
|
ret = g_list_prepend (ret, g_strdup (candidate->version));
|
2010-07-27 13:06:54 +02:00
|
|
|
free_candidate (candidate);
|
|
|
|
}
|
|
|
|
g_slist_free (candidates);
|
2010-08-16 22:39:19 +02:00
|
|
|
|
|
|
|
/* The currently loaded version of a namespace is also part of the
|
|
|
|
* available versions, as it could have been loaded using
|
|
|
|
* require_private().
|
|
|
|
*/
|
2023-11-08 15:17:52 +01:00
|
|
|
if (gi_repository_is_registered (repository, namespace_, NULL))
|
2010-08-18 22:26:48 +02:00
|
|
|
{
|
2023-11-08 15:17:52 +01:00
|
|
|
loaded_version = gi_repository_get_version (repository, namespace_);
|
2010-08-18 22:26:48 +02:00
|
|
|
if (loaded_version && !g_list_find_custom (ret, loaded_version, g_str_equal))
|
|
|
|
ret = g_list_prepend (ret, g_strdup (loaded_version));
|
|
|
|
}
|
2010-08-16 22:39:19 +02:00
|
|
|
|
2010-07-27 13:06:54 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2010-08-31 22:36:06 +02:00
|
|
|
static GITypelib *
|
2010-07-30 20:38:34 +02:00
|
|
|
require_internal (GIRepository *repository,
|
|
|
|
const gchar *namespace,
|
|
|
|
const gchar *version,
|
|
|
|
GIRepositoryLoadFlags flags,
|
|
|
|
GSList *search_path,
|
|
|
|
GError **error)
|
2008-02-08 16:31:03 +01:00
|
|
|
{
|
|
|
|
GMappedFile *mfile;
|
2010-08-31 22:36:06 +02:00
|
|
|
GITypelib *ret = NULL;
|
2008-10-12 06:51:48 +02:00
|
|
|
Header *header;
|
2010-08-31 22:36:06 +02:00
|
|
|
GITypelib *typelib = NULL;
|
Bug 556543 – reduce compiler warnings
2008-10-16 Tommi Komulainen <tommi.komulainen@iki.fi>
Bug 556543 – reduce compiler warnings
* girepository/ginfo.c:
* girepository/girepository.c (register_internal,
count_interfaces, find_interface, find_namespace_version,
parse_version, g_irepository_require):
* girepository/girmodule.c (g_ir_module_build_typelib):
* girepository/girnode.c (init_stats, dump_stats,
_g_irnode_init_stats, _g_irnode_dump_stats,
g_ir_node_can_have_member):
* girepository/girparser.c (firstpass_end_element_handler,
locate_gir, parse_basic, parse_type_internal, resolve_aliases,
start_alias, start_type, end_type_top, parse_include, cleanup,
post_filter):
* girepository/gtypelib.c (validate_function_blob, validate_enum_blob):
* giscanner/giscannermodule.c (directive_get_options,
type_get_child_list):
* giscanner/scannerlexer.l (parse_gtkdoc):
* giscanner/scannerparser.y (ctype_free):
* giscanner/sourcescanner.c:
* giscanner/sourcescanner.h (gi_source_scanner_parse_macros):
* tests/types/gitesttypes.c:
* tools/compiler.c (main):
* tools/generate.c (write_repository): Remove unused variables
and code, add missing includes, declarations and case
statements.
svn path=/trunk/; revision=730
2008-10-16 19:07:05 +02:00
|
|
|
const gchar *typelib_namespace, *typelib_version;
|
2023-11-08 15:17:52 +01:00
|
|
|
gboolean allow_lazy = (flags & GI_REPOSITORY_LOAD_FLAG_LAZY) > 0;
|
2008-08-30 22:31:12 +02:00
|
|
|
gboolean is_lazy;
|
2008-10-12 06:51:48 +02:00
|
|
|
char *version_conflict = NULL;
|
|
|
|
char *path = NULL;
|
|
|
|
char *tmp_version = NULL;
|
|
|
|
|
|
|
|
g_return_val_if_fail (namespace != NULL, FALSE);
|
2008-02-08 16:31:03 +01:00
|
|
|
|
2008-08-30 22:31:07 +02:00
|
|
|
repository = get_repository (repository);
|
2008-02-08 16:31:03 +01:00
|
|
|
|
2010-03-24 19:00:06 +01:00
|
|
|
typelib = get_registered_status (repository, namespace, version, allow_lazy,
|
2008-10-25 17:48:50 +02:00
|
|
|
&is_lazy, &version_conflict);
|
|
|
|
if (typelib)
|
|
|
|
return typelib;
|
2008-02-08 16:31:03 +01:00
|
|
|
|
2008-10-12 06:51:48 +02:00
|
|
|
if (version_conflict != NULL)
|
2008-08-21 08:47:49 +02:00
|
|
|
{
|
2023-11-08 15:17:52 +01:00
|
|
|
g_set_error (error, GI_REPOSITORY_ERROR,
|
|
|
|
GI_REPOSITORY_ERROR_NAMESPACE_VERSION_CONFLICT,
|
2008-10-12 06:51:48 +02:00
|
|
|
"Requiring namespace '%s' version '%s', but '%s' is already loaded",
|
|
|
|
namespace, version, version_conflict);
|
2008-10-25 17:48:50 +02:00
|
|
|
return NULL;
|
2008-10-12 06:51:48 +02:00
|
|
|
}
|
2008-08-21 08:47:49 +02:00
|
|
|
|
2008-10-12 06:51:48 +02:00
|
|
|
if (version != NULL)
|
|
|
|
{
|
2010-07-30 20:38:34 +02:00
|
|
|
mfile = find_namespace_version (namespace, version,
|
|
|
|
search_path, &path);
|
2008-10-12 06:51:48 +02:00
|
|
|
tmp_version = g_strdup (version);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-07-30 20:38:34 +02:00
|
|
|
mfile = find_namespace_latest (namespace, search_path,
|
|
|
|
&tmp_version, &path);
|
2008-10-12 06:51:48 +02:00
|
|
|
}
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-10-12 06:51:48 +02:00
|
|
|
if (mfile == NULL)
|
|
|
|
{
|
|
|
|
if (version != NULL)
|
2023-11-08 15:17:52 +01:00
|
|
|
g_set_error (error, GI_REPOSITORY_ERROR,
|
|
|
|
GI_REPOSITORY_ERROR_TYPELIB_NOT_FOUND,
|
2008-10-16 03:40:29 +02:00
|
|
|
"Typelib file for namespace '%s', version '%s' not found",
|
2008-10-12 06:51:48 +02:00
|
|
|
namespace, version);
|
|
|
|
else
|
2023-11-08 15:17:52 +01:00
|
|
|
g_set_error (error, GI_REPOSITORY_ERROR,
|
|
|
|
GI_REPOSITORY_ERROR_TYPELIB_NOT_FOUND,
|
2008-10-12 06:51:48 +02:00
|
|
|
"Typelib file for namespace '%s' (any version) not found",
|
|
|
|
namespace);
|
|
|
|
goto out;
|
|
|
|
}
|
2008-08-21 08:47:49 +02:00
|
|
|
|
2010-07-22 19:46:33 +02:00
|
|
|
{
|
|
|
|
GError *temp_error = NULL;
|
2023-11-08 15:17:52 +01:00
|
|
|
typelib = gi_typelib_new_from_mapped_file (mfile, &temp_error);
|
2010-07-22 19:46:33 +02:00
|
|
|
if (!typelib)
|
|
|
|
{
|
2023-11-08 15:17:52 +01:00
|
|
|
g_set_error (error, GI_REPOSITORY_ERROR,
|
|
|
|
GI_REPOSITORY_ERROR_TYPELIB_NOT_FOUND,
|
2010-07-22 19:46:33 +02:00
|
|
|
"Failed to load typelib file '%s' for namespace '%s': %s",
|
|
|
|
path, namespace, temp_error->message);
|
|
|
|
g_clear_error (&temp_error);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
}
|
2008-10-12 06:51:48 +02:00
|
|
|
header = (Header *) typelib->data;
|
2023-11-08 15:17:52 +01:00
|
|
|
typelib_namespace = gi_typelib_get_string (typelib, header->namespace);
|
|
|
|
typelib_version = gi_typelib_get_string (typelib, header->nsversion);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-10-12 06:51:48 +02:00
|
|
|
if (strcmp (typelib_namespace, namespace) != 0)
|
2008-08-21 08:47:49 +02:00
|
|
|
{
|
2023-11-08 15:17:52 +01:00
|
|
|
g_set_error (error, GI_REPOSITORY_ERROR,
|
|
|
|
GI_REPOSITORY_ERROR_NAMESPACE_MISMATCH,
|
2008-10-12 06:51:48 +02:00
|
|
|
"Typelib file %s for namespace '%s' contains "
|
|
|
|
"namespace '%s' which doesn't match the file name",
|
|
|
|
path, namespace, typelib_namespace);
|
2023-11-08 15:17:52 +01:00
|
|
|
gi_typelib_free (typelib);
|
2008-10-12 06:51:48 +02:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
if (version != NULL && strcmp (typelib_version, version) != 0)
|
|
|
|
{
|
2023-11-08 15:17:52 +01:00
|
|
|
g_set_error (error, GI_REPOSITORY_ERROR,
|
|
|
|
GI_REPOSITORY_ERROR_NAMESPACE_MISMATCH,
|
2008-10-12 06:51:48 +02:00
|
|
|
"Typelib file %s for namespace '%s' contains "
|
|
|
|
"version '%s' which doesn't match the expected version '%s'",
|
|
|
|
path, namespace, typelib_version, version);
|
2023-11-08 15:17:52 +01:00
|
|
|
gi_typelib_free (typelib);
|
2008-10-12 06:51:48 +02:00
|
|
|
goto out;
|
2008-02-08 16:31:03 +01:00
|
|
|
}
|
2008-08-21 08:47:49 +02:00
|
|
|
|
2010-03-24 19:00:06 +01:00
|
|
|
if (!register_internal (repository, path, allow_lazy,
|
2008-08-30 22:31:12 +02:00
|
|
|
typelib, error))
|
2008-08-30 22:31:07 +02:00
|
|
|
{
|
2023-11-08 15:17:52 +01:00
|
|
|
gi_typelib_free (typelib);
|
2008-10-12 06:51:48 +02:00
|
|
|
goto out;
|
2008-08-30 22:31:07 +02:00
|
|
|
}
|
2008-10-25 17:48:50 +02:00
|
|
|
ret = typelib;
|
2008-10-12 06:51:48 +02:00
|
|
|
out:
|
|
|
|
g_free (tmp_version);
|
|
|
|
g_free (path);
|
2010-03-24 19:00:06 +01:00
|
|
|
return ret;
|
2008-02-08 16:31:03 +01:00
|
|
|
}
|
|
|
|
|
2010-07-30 20:38:34 +02:00
|
|
|
/**
|
2023-11-08 15:17:52 +01:00
|
|
|
* gi_repository_require:
|
2013-10-10 22:21:18 +02:00
|
|
|
* @repository: (allow-none): A #GIRepository or %NULL for the singleton
|
|
|
|
* process-global default #GIRepository
|
2010-07-30 20:38:34 +02:00
|
|
|
* @namespace_: GI namespace to use, e.g. "Gtk"
|
|
|
|
* @version: (allow-none): Version of namespace, may be %NULL for latest
|
|
|
|
* @flags: Set of %GIRepositoryLoadFlags, may be 0
|
|
|
|
* @error: a #GError.
|
|
|
|
*
|
|
|
|
* Force the namespace @namespace_ to be loaded if it isn't already.
|
|
|
|
* If @namespace_ is not loaded, this function will search for a
|
|
|
|
* ".typelib" file using the repository search path. In addition, a
|
|
|
|
* version @version of namespace may be specified. If @version is
|
|
|
|
* not specified, the latest will be used.
|
|
|
|
*
|
2010-09-10 14:33:15 +02:00
|
|
|
* Returns: (transfer none): a pointer to the #GITypelib if successful, %NULL otherwise
|
2010-07-30 20:38:34 +02:00
|
|
|
*/
|
2010-08-31 22:36:06 +02:00
|
|
|
GITypelib *
|
2023-11-08 15:17:52 +01:00
|
|
|
gi_repository_require (GIRepository *repository,
|
2010-07-30 20:38:34 +02:00
|
|
|
const gchar *namespace,
|
|
|
|
const gchar *version,
|
|
|
|
GIRepositoryLoadFlags flags,
|
|
|
|
GError **error)
|
|
|
|
{
|
2010-08-31 22:36:06 +02:00
|
|
|
GITypelib *typelib;
|
2010-07-30 20:38:34 +02:00
|
|
|
|
2016-04-28 16:22:38 +02:00
|
|
|
init_globals ();
|
2010-07-30 20:38:34 +02:00
|
|
|
typelib = require_internal (repository, namespace, version, flags,
|
2018-07-29 15:56:35 +02:00
|
|
|
typelib_search_path, error);
|
2010-07-30 20:38:34 +02:00
|
|
|
|
|
|
|
return typelib;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2023-11-08 15:17:52 +01:00
|
|
|
* gi_repository_require_private:
|
2013-10-10 22:21:18 +02:00
|
|
|
* @repository: (allow-none): A #GIRepository or %NULL for the singleton
|
|
|
|
* process-global default #GIRepository
|
2010-07-30 20:38:34 +02:00
|
|
|
* @typelib_dir: Private directory where to find the requested typelib
|
|
|
|
* @namespace_: GI namespace to use, e.g. "Gtk"
|
|
|
|
* @version: (allow-none): Version of namespace, may be %NULL for latest
|
|
|
|
* @flags: Set of %GIRepositoryLoadFlags, may be 0
|
|
|
|
* @error: a #GError.
|
|
|
|
*
|
|
|
|
* Force the namespace @namespace_ to be loaded if it isn't already.
|
|
|
|
* If @namespace_ is not loaded, this function will search for a
|
|
|
|
* ".typelib" file within the private directory only. In addition, a
|
|
|
|
* version @version of namespace should be specified. If @version is
|
|
|
|
* not specified, the latest will be used.
|
|
|
|
*
|
2010-09-10 14:33:15 +02:00
|
|
|
* Returns: (transfer none): a pointer to the #GITypelib if successful, %NULL otherwise
|
2010-07-30 20:38:34 +02:00
|
|
|
*/
|
2010-08-31 22:36:06 +02:00
|
|
|
GITypelib *
|
2023-11-08 15:17:52 +01:00
|
|
|
gi_repository_require_private (GIRepository *repository,
|
2010-07-30 20:38:34 +02:00
|
|
|
const gchar *typelib_dir,
|
|
|
|
const gchar *namespace,
|
|
|
|
const gchar *version,
|
|
|
|
GIRepositoryLoadFlags flags,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
GSList search_path = { (gpointer) typelib_dir, NULL };
|
|
|
|
|
|
|
|
return require_internal (repository, namespace, version, flags,
|
|
|
|
&search_path, error);
|
|
|
|
}
|
|
|
|
|
2008-11-13 20:57:09 +01:00
|
|
|
static gboolean
|
2023-11-08 15:17:52 +01:00
|
|
|
gi_repository_introspect_cb (const char *option_name,
|
2008-11-13 20:57:09 +01:00
|
|
|
const char *value,
|
|
|
|
gpointer data,
|
|
|
|
GError **error)
|
|
|
|
{
|
2010-07-31 12:22:52 +02:00
|
|
|
GError *tmp_error = NULL;
|
2023-12-12 23:43:11 +01:00
|
|
|
char **args;
|
|
|
|
|
|
|
|
args = g_strsplit (value, ",", 2);
|
|
|
|
|
|
|
|
if (!gi_repository_dump (args[0], args[1], &tmp_error))
|
2010-07-31 12:22:52 +02:00
|
|
|
{
|
|
|
|
g_error ("Failed to extract GType data: %s",
|
|
|
|
tmp_error->message);
|
|
|
|
exit (1);
|
|
|
|
}
|
|
|
|
exit (0);
|
2008-11-13 20:57:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static const GOptionEntry introspection_args[] = {
|
|
|
|
{ "introspect-dump", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_CALLBACK,
|
2023-11-08 15:17:52 +01:00
|
|
|
gi_repository_introspect_cb, "Dump introspection information",
|
2008-11-13 20:57:09 +01:00
|
|
|
"infile.txt,outfile.xml" },
|
2023-10-25 20:03:07 +02:00
|
|
|
G_OPTION_ENTRY_NULL
|
2008-11-13 20:57:09 +01:00
|
|
|
};
|
|
|
|
|
2010-08-31 22:26:17 +02:00
|
|
|
/**
|
2023-11-08 15:17:52 +01:00
|
|
|
* gi_repository_get_option_group:
|
2010-08-31 22:26:17 +02:00
|
|
|
*
|
|
|
|
* Obtain the option group for girepository, it's used
|
|
|
|
* by the dumper and for programs that wants to provide
|
|
|
|
* introspection information
|
|
|
|
*
|
|
|
|
* Returns: (transfer full): the option group
|
|
|
|
*/
|
2008-11-13 20:57:09 +01:00
|
|
|
GOptionGroup *
|
2023-11-08 15:17:52 +01:00
|
|
|
gi_repository_get_option_group (void)
|
2008-11-13 20:57:09 +01:00
|
|
|
{
|
|
|
|
GOptionGroup *group;
|
|
|
|
group = g_option_group_new ("girepository", "Introspection Options", "Show Introspection Options", NULL, NULL);
|
|
|
|
|
|
|
|
g_option_group_add_entries (group, introspection_args);
|
|
|
|
return group;
|
|
|
|
}
|
2008-02-08 16:31:03 +01:00
|
|
|
|
|
|
|
GQuark
|
2023-11-08 15:17:52 +01:00
|
|
|
gi_repository_error_quark (void)
|
2008-02-08 16:31:03 +01:00
|
|
|
{
|
|
|
|
static GQuark quark = 0;
|
|
|
|
if (quark == 0)
|
|
|
|
quark = g_quark_from_static_string ("g-irepository-error-quark");
|
|
|
|
return quark;
|
|
|
|
}
|
2008-08-18 10:52:47 +02:00
|
|
|
|
2010-07-28 13:52:45 +02:00
|
|
|
/**
|
2023-11-08 15:17:52 +01:00
|
|
|
* gi_type_tag_to_string:
|
2010-07-28 13:52:45 +02:00
|
|
|
* @type: the type_tag
|
|
|
|
*
|
|
|
|
* Obtain a string representation of @type
|
|
|
|
*
|
|
|
|
* Returns: the string
|
|
|
|
*/
|
2008-08-18 10:52:47 +02:00
|
|
|
const gchar*
|
2023-11-08 15:17:52 +01:00
|
|
|
gi_type_tag_to_string (GITypeTag type)
|
2008-08-18 10:52:47 +02:00
|
|
|
{
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case GI_TYPE_TAG_VOID:
|
|
|
|
return "void";
|
|
|
|
case GI_TYPE_TAG_BOOLEAN:
|
2010-07-22 03:06:17 +02:00
|
|
|
return "gboolean";
|
2008-08-18 10:52:47 +02:00
|
|
|
case GI_TYPE_TAG_INT8:
|
2010-07-22 03:06:17 +02:00
|
|
|
return "gint8";
|
2008-08-18 10:52:47 +02:00
|
|
|
case GI_TYPE_TAG_UINT8:
|
2010-07-22 03:06:17 +02:00
|
|
|
return "guint8";
|
2008-08-18 10:52:47 +02:00
|
|
|
case GI_TYPE_TAG_INT16:
|
2010-07-22 03:06:17 +02:00
|
|
|
return "gint16";
|
2008-08-18 10:52:47 +02:00
|
|
|
case GI_TYPE_TAG_UINT16:
|
2010-07-22 03:06:17 +02:00
|
|
|
return "guint16";
|
2008-08-18 10:52:47 +02:00
|
|
|
case GI_TYPE_TAG_INT32:
|
2010-07-22 03:06:17 +02:00
|
|
|
return "gint32";
|
2008-08-18 10:52:47 +02:00
|
|
|
case GI_TYPE_TAG_UINT32:
|
2010-07-22 03:06:17 +02:00
|
|
|
return "guint32";
|
2008-08-18 10:52:47 +02:00
|
|
|
case GI_TYPE_TAG_INT64:
|
2010-07-22 03:06:17 +02:00
|
|
|
return "gint64";
|
2008-08-18 10:52:47 +02:00
|
|
|
case GI_TYPE_TAG_UINT64:
|
2010-07-22 03:06:17 +02:00
|
|
|
return "guint64";
|
2008-08-18 10:52:47 +02:00
|
|
|
case GI_TYPE_TAG_FLOAT:
|
2010-07-22 03:06:17 +02:00
|
|
|
return "gfloat";
|
2008-08-18 10:52:47 +02:00
|
|
|
case GI_TYPE_TAG_DOUBLE:
|
2010-07-22 03:06:17 +02:00
|
|
|
return "gdouble";
|
2010-10-26 17:12:26 +02:00
|
|
|
case GI_TYPE_TAG_UNICHAR:
|
|
|
|
return "gunichar";
|
2008-10-02 15:25:46 +02:00
|
|
|
case GI_TYPE_TAG_GTYPE:
|
|
|
|
return "GType";
|
2008-08-18 10:52:47 +02:00
|
|
|
case GI_TYPE_TAG_UTF8:
|
|
|
|
return "utf8";
|
|
|
|
case GI_TYPE_TAG_FILENAME:
|
|
|
|
return "filename";
|
|
|
|
case GI_TYPE_TAG_ARRAY:
|
|
|
|
return "array";
|
|
|
|
case GI_TYPE_TAG_INTERFACE:
|
|
|
|
return "interface";
|
|
|
|
case GI_TYPE_TAG_GLIST:
|
|
|
|
return "glist";
|
|
|
|
case GI_TYPE_TAG_GSLIST:
|
|
|
|
return "gslist";
|
|
|
|
case GI_TYPE_TAG_GHASH:
|
|
|
|
return "ghash";
|
|
|
|
case GI_TYPE_TAG_ERROR:
|
|
|
|
return "error";
|
|
|
|
default:
|
|
|
|
return "unknown";
|
|
|
|
}
|
|
|
|
}
|
2010-07-28 12:24:10 +02:00
|
|
|
|
|
|
|
/**
|
2023-11-08 15:17:52 +01:00
|
|
|
* gi_info_type_to_string:
|
2010-07-28 13:52:45 +02:00
|
|
|
* @type: the info type
|
|
|
|
*
|
|
|
|
* Obtain a string representation of @type
|
2010-07-28 12:24:10 +02:00
|
|
|
*
|
2010-07-28 13:52:45 +02:00
|
|
|
* Returns: the string
|
2010-07-28 12:24:10 +02:00
|
|
|
*/
|
|
|
|
const gchar*
|
2023-11-08 15:17:52 +01:00
|
|
|
gi_info_type_to_string (GIInfoType type)
|
2010-07-28 12:24:10 +02:00
|
|
|
{
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case GI_INFO_TYPE_INVALID:
|
|
|
|
return "invalid";
|
|
|
|
case GI_INFO_TYPE_FUNCTION:
|
|
|
|
return "function";
|
|
|
|
case GI_INFO_TYPE_CALLBACK:
|
|
|
|
return "callback";
|
|
|
|
case GI_INFO_TYPE_STRUCT:
|
|
|
|
return "struct";
|
|
|
|
case GI_INFO_TYPE_BOXED:
|
|
|
|
return "boxed";
|
|
|
|
case GI_INFO_TYPE_ENUM:
|
|
|
|
return "enum";
|
|
|
|
case GI_INFO_TYPE_FLAGS:
|
|
|
|
return "flags";
|
|
|
|
case GI_INFO_TYPE_OBJECT:
|
|
|
|
return "object";
|
|
|
|
case GI_INFO_TYPE_INTERFACE:
|
|
|
|
return "interface";
|
|
|
|
case GI_INFO_TYPE_CONSTANT:
|
|
|
|
return "constant";
|
|
|
|
case GI_INFO_TYPE_UNION:
|
|
|
|
return "union";
|
|
|
|
case GI_INFO_TYPE_VALUE:
|
|
|
|
return "value";
|
|
|
|
case GI_INFO_TYPE_SIGNAL:
|
|
|
|
return "signal";
|
|
|
|
case GI_INFO_TYPE_VFUNC:
|
|
|
|
return "vfunc";
|
|
|
|
case GI_INFO_TYPE_PROPERTY:
|
|
|
|
return "property";
|
|
|
|
case GI_INFO_TYPE_FIELD:
|
|
|
|
return "field";
|
|
|
|
case GI_INFO_TYPE_ARG:
|
|
|
|
return "arg";
|
|
|
|
case GI_INFO_TYPE_TYPE:
|
|
|
|
return "type";
|
|
|
|
case GI_INFO_TYPE_UNRESOLVED:
|
|
|
|
return "unresolved";
|
|
|
|
default:
|
|
|
|
return "unknown";
|
|
|
|
}
|
|
|
|
}
|