summaryrefslogtreecommitdiff
path: root/girepository/gitypelib.c
diff options
context:
space:
mode:
Diffstat (limited to 'girepository/gitypelib.c')
-rw-r--r--girepository/gitypelib.c241
1 files changed, 175 insertions, 66 deletions
diff --git a/girepository/gitypelib.c b/girepository/gitypelib.c
index 2af17e96..d88924a6 100644
--- a/girepository/gitypelib.c
+++ b/girepository/gitypelib.c
@@ -198,55 +198,17 @@ g_typelib_get_dir_entry_by_name (GITypelib *typelib,
}
DirEntry *
-g_typelib_get_dir_entry_by_gtype (GITypelib *typelib,
- gboolean fastpass,
- GType gtype)
+g_typelib_get_dir_entry_by_gtype_name (GITypelib *typelib,
+ const gchar *gtype_name)
{
Header *header = (Header *)typelib->data;
- guint n_entries = header->n_local_entries;
- const char *gtype_name = g_type_name (gtype);
- DirEntry *entry;
guint i;
- const char *c_prefix;
-
- /* There is a corner case regarding GdkRectangle. GdkRectangle is a
- boxed type, but it is just an alias to boxed struct
- CairoRectangleInt. Scanner automatically converts all references
- to GdkRectangle to CairoRectangleInt, so GdkRectangle does not
- appear in the typelibs at all, although user code might query it.
- So if we get such query, we also change it to lookup of
- CairoRectangleInt.
- https://bugzilla.gnome.org/show_bug.cgi?id=655423 */
- if (!fastpass && !strcmp (gtype_name, "GdkRectangle"))
- gtype_name = "CairoRectangleInt";
-
- /* 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.
- *
- * However, not every class library necessarily conforms to this,
- * e.g. Clutter has Cogl inside it. So, we split this into two
- * passes. First we try a lookup, skipping things which don't
- * have the prefix. If that fails then we try a global lookup,
- * ignoring the prefix.
- *
- * See http://bugzilla.gnome.org/show_bug.cgi?id=564016
- */
- c_prefix = g_typelib_get_string (typelib, header->c_prefix);
- if (fastpass && c_prefix != NULL)
- {
- if (g_ascii_strncasecmp (c_prefix, gtype_name, strlen (c_prefix)) != 0)
- return NULL;
- }
- for (i = 1; i <= n_entries; i++)
+ for (i = 1; i <= header->n_local_entries; i++)
{
RegisteredTypeBlob *blob;
const char *type;
-
- entry = g_typelib_get_dir_entry (typelib, i);
+ DirEntry *entry = g_typelib_get_dir_entry (typelib, i);
if (!BLOB_IS_REGISTERED_TYPE (entry))
continue;
@@ -261,6 +223,110 @@ g_typelib_get_dir_entry_by_gtype (GITypelib *typelib,
return NULL;
}
+typedef struct {
+ const char *s;
+ const char *separator;
+ gsize sep_len;
+ GString buf;
+} StrSplitIter;
+
+static void
+strsplit_iter_init (StrSplitIter *iter,
+ const char *s,
+ const char *separator)
+{
+ iter->s = s;
+ iter->separator = separator;
+ iter->sep_len = strlen (separator);
+ iter->buf.str = NULL;
+ iter->buf.len = 0;
+ iter->buf.allocated_len = 0;
+}
+
+static gboolean
+strsplit_iter_next (StrSplitIter *iter,
+ char **out_val)
+{
+ const char *s = iter->s;
+ const char *next;
+ gsize len;
+
+ if (!s)
+ return FALSE;
+ next = strstr (s, iter->separator);
+ if (next)
+ {
+ iter->s = next + iter->sep_len;
+ len = next - s;
+ }
+ else
+ {
+ iter->s = NULL;
+ len = strlen (s);
+ }
+ if (len == 0)
+ {
+ *out_val = "";
+ }
+ else
+ {
+ g_string_overwrite_len (&iter->buf, 0, s, (gssize)len);
+ *out_val = iter->buf.str;
+ }
+ return TRUE;
+}
+
+static void
+strsplit_iter_clear (StrSplitIter *iter)
+{
+ g_free (iter->buf.str);
+}
+
+gboolean
+g_typelib_matches_gtype_name_prefix (GITypelib *typelib,
+ const gchar *gtype_name)
+{
+ Header *header = (Header *)typelib->data;
+ const char *c_prefix;
+ gchar *prefix;
+ gboolean ret = FALSE;
+ StrSplitIter split_iter;
+ gsize gtype_name_len;
+
+ c_prefix = g_typelib_get_string (typelib, header->c_prefix);
+ if (c_prefix == NULL || strlen (c_prefix) == 0)
+ return FALSE;
+
+ gtype_name_len = strlen (gtype_name);
+
+ /* c_prefix is a comma separated string of supported prefixes
+ * in the typelib.
+ * We match the specified gtype_name if the gtype_name starts
+ * with the prefix, and is followed by a capital letter.
+ * For example, a typelib offering the 'Gdk' prefix does match
+ * GdkX11Cursor, however a typelib offering the 'G' prefix does not.
+ */
+ strsplit_iter_init (&split_iter, c_prefix, ",");
+ while (strsplit_iter_next (&split_iter, &prefix))
+ {
+ size_t len = strlen (prefix);
+
+ if (gtype_name_len < len)
+ continue;
+
+ if (strncmp (prefix, gtype_name, len) != 0)
+ continue;
+
+ if (g_ascii_isupper (gtype_name[len]))
+ {
+ ret = TRUE;
+ break;
+ }
+ }
+ strsplit_iter_clear (&split_iter);
+ return ret;
+}
+
DirEntry *
g_typelib_get_dir_entry_by_error_domain (GITypelib *typelib,
GQuark error_domain)
@@ -2062,6 +2128,72 @@ g_typelib_error_quark (void)
return quark;
}
+static GSList *library_paths;
+
+/**
+ * g_irepository_prepend_library_path:
+ * @directory: (type filename): a single directory to scan for shared libraries
+ *
+ * Prepends @directory to the search path that is used to
+ * search shared libraries referenced by imported namespaces.
+ * Multiple calls to this function all contribute to the final
+ * list of paths.
+ * The list of paths is unique and shared for all #GIRepository
+ * instances across the process, but it doesn't affect namespaces
+ * imported before the call.
+ *
+ * If the library is not found in the directories configured
+ * in this way, loading will fall back to the system library
+ * path (ie. LD_LIBRARY_PATH and DT_RPATH in ELF systems).
+ * See the documentation of your dynamic linker for full details.
+ *
+ * Since: 1.35.8
+ */
+void
+g_irepository_prepend_library_path (const char *directory)
+{
+ library_paths = g_slist_prepend (library_paths,
+ g_strdup (directory));
+}
+
+/* Note on the GModule flags used by this function:
+
+ * Glade's autoconnect feature and OpenGL's extension mechanism
+ * as used by Clutter rely on g_module_open(NULL) to work as a means of
+ * accessing the app's symbols. This keeps us from using
+ * G_MODULE_BIND_LOCAL. BIND_LOCAL may have other issues as well;
+ * in general libraries are not expecting multiple copies of
+ * themselves and are not expecting to be unloaded. So we just
+ * load modules globally for now.
+ */
+static GModule *
+load_one_shared_library (const char *shlib)
+{
+ GSList *p;
+ GModule *m;
+
+ if (!g_path_is_absolute (shlib))
+ {
+ /* First try in configured library paths */
+ for (p = library_paths; p; p = p->next)
+ {
+ char *path = g_build_filename (p->data, shlib, NULL);
+
+ m = g_module_open (path, G_MODULE_BIND_LAZY);
+
+ g_free (path);
+ if (m != NULL)
+ return m;
+ }
+ }
+
+ /* Then try loading from standard paths */
+ /* Do not attempt to fix up shlib to replace .la with .so:
+ it's done by GModule anyway.
+ */
+ return g_module_open (shlib, G_MODULE_BIND_LAZY);
+}
+
static void
_g_typelib_do_dlopen (GITypelib *typelib)
{
@@ -2091,30 +2223,7 @@ _g_typelib_do_dlopen (GITypelib *typelib)
{
GModule *module;
- /* Glade's autoconnect feature and OpenGL's extension mechanism
- * as used by Clutter rely on g_module_open(NULL) to work as a means of
- * accessing the app's symbols. This keeps us from using
- * G_MODULE_BIND_LOCAL. BIND_LOCAL may have other issues as well;
- * in general libraries are not expecting multiple copies of
- * themselves and are not expecting to be unloaded. So we just
- * load modules globally for now.
- */
-
- module = g_module_open (shlibs[i], G_MODULE_BIND_LAZY);
-
- if (module == NULL)
- {
- GString *shlib_full = g_string_new (shlibs[i]);
-
- module = g_module_open (shlib_full->str, G_MODULE_BIND_LAZY);
- if (module == NULL)
- {
- g_string_overwrite (shlib_full, strlen (shlib_full->str)-2, SHLIB_SUFFIX);
- module = g_module_open (shlib_full->str, G_MODULE_BIND_LAZY);
- }
-
- g_string_free (shlib_full, TRUE);
- }
+ module = load_one_shared_library (shlibs[i]);
if (module == NULL)
{