summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--girepository/girepository.c76
-rw-r--r--girepository/girepository.h2
-rw-r--r--girepository/girmodule.c19
-rw-r--r--girepository/girmodule.h4
-rw-r--r--girepository/girparser.c6
-rw-r--r--girepository/gtypelib.c2
-rw-r--r--girepository/gtypelib.h1
-rw-r--r--tests/scanner/BarApp-1.0-expected.tgir2
-rw-r--r--tests/scanner/GtkFrob-1.0-expected.tgir2
-rw-r--r--tests/scanner/annotation-1.0-expected.tgir2
-rw-r--r--tests/scanner/drawable-1.0-expected.tgir2
-rw-r--r--tests/scanner/foo-1.0-expected.tgir2
-rw-r--r--tests/scanner/utility-1.0-expected.tgir2
-rw-r--r--tools/generate.c4
14 files changed, 108 insertions, 18 deletions
diff --git a/girepository/girepository.c b/girepository/girepository.c
index 06ea13c5..a2a8504d 100644
--- a/girepository/girepository.c
+++ b/girepository/girepository.c
@@ -517,6 +517,7 @@ typedef struct
GIRepository *repo;
gint index;
const gchar *name;
+ gboolean type_firstpass;
const gchar *type;
GIBaseInfo *iface;
} IfaceData;
@@ -528,6 +529,7 @@ find_interface (gpointer key,
{
gint i;
GTypelib *typelib = (GTypelib *)value;
+ Header *header = (Header *) typelib->data;
IfaceData *iface_data = (IfaceData *)data;
gint index;
gint n_entries;
@@ -553,6 +555,28 @@ find_interface (gpointer key,
}
else if (iface_data->type)
{
+ const char *c_prefix;
+ /* 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 (iface_data->type_firstpass && c_prefix != NULL)
+ {
+ if (g_ascii_strncasecmp (c_prefix, iface_data->type, strlen (c_prefix)) != 0)
+ return;
+ }
+
for (i = 1; i <= n_entries; i++)
{
RegisteredTypeBlob *blob;
@@ -638,8 +662,8 @@ g_irepository_get_info (GIRepository *repository,
* 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
- * arbitrary GType - thus, this function will function most reliably
- * when you have expect the GType to be from a known namespace.
+ * arbitrary GType - thus, this function will operate most reliably
+ * when you know the GType to originate from be from a loaded namespace.
*
* Returns: #GIBaseInfo representing metadata about @type, or %NULL
*/
@@ -659,6 +683,7 @@ g_irepository_find_by_gtype (GIRepository *repository,
data.repo = repository;
data.name = NULL;
+ data.type_firstpass = TRUE;
data.type = g_type_name (gtype);
data.index = -1;
data.iface = NULL;
@@ -666,12 +691,19 @@ g_irepository_find_by_gtype (GIRepository *repository,
g_hash_table_foreach (repository->priv->typelibs, find_interface, &data);
g_hash_table_foreach (repository->priv->lazy_typelibs, find_interface, &data);
+ /* We do two passes; see comment in find_interface */
+ if (!data.iface)
+ {
+ data.type_firstpass = FALSE;
+ g_hash_table_foreach (repository->priv->typelibs, find_interface, &data);
+ g_hash_table_foreach (repository->priv->lazy_typelibs, find_interface, &data);
+ }
+
if (data.iface)
g_hash_table_insert (repository->priv->info_by_gtype,
(gpointer) gtype,
g_base_info_ref (data.iface));
-
return data.iface;
}
@@ -824,7 +856,43 @@ g_irepository_get_shared_library (GIRepository *repository,
}
/**
- * g_irepository_get_typelib_path:
+ * g_irepository_get_c_prefix
+ * @repository: A #GIRepository, may be %NULL for the default
+ * @namespace: Namespace to inspect
+ *
+ * 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
+ * such as #g_irepository_require before calling this function.
+ *
+ * Returns: C namespace prefix, or %NULL if none associated
+ */
+const gchar *
+g_irepository_get_c_prefix (GIRepository *repository,
+ const gchar *namespace_)
+{
+ GTypelib *typelib;
+ 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;
+ if (header->shared_library)
+ return g_typelib_get_string (typelib, header->c_prefix);
+ else
+ return NULL;
+}
+
+/**
+ * g_irepository_get_typelib_path
* @repository: Repository, may be %NULL for the default
* @namespace_: GI namespace to use, e.g. "Gtk"
*
diff --git a/girepository/girepository.h b/girepository/girepository.h
index 1058570f..efc6aca0 100644
--- a/girepository/girepository.h
+++ b/girepository/girepository.h
@@ -108,6 +108,8 @@ const gchar * g_irepository_get_typelib_path (GIRepository *repository,
const gchar *namespace_);
const gchar * g_irepository_get_shared_library (GIRepository *repository,
const gchar *namespace_);
+const gchar * g_irepository_get_c_prefix (GIRepository *repository,
+ const gchar *namespace_);
const gchar * g_irepository_get_version (GIRepository *repository,
const gchar *namespace_);
diff --git a/girepository/girmodule.c b/girepository/girmodule.c
index 96ee9ce9..bf1e856b 100644
--- a/girepository/girmodule.c
+++ b/girepository/girmodule.c
@@ -31,7 +31,8 @@
GIrModule *
g_ir_module_new (const gchar *name,
const gchar *version,
- const gchar *shared_library)
+ const gchar *shared_library,
+ const gchar *c_prefix)
{
GIrModule *module;
@@ -43,6 +44,7 @@ g_ir_module_new (const gchar *name,
module->shared_library = g_strdup (shared_library);
else
module->shared_library = NULL;
+ module->c_prefix = g_strdup (c_prefix);
module->dependencies = NULL;
module->entries = NULL;
@@ -229,11 +231,13 @@ g_ir_module_build_typelib (GIrModule *module,
}
/* Adjust size for strings allocated in header below specially */
- size += strlen (module->name);
+ size += ALIGN_VALUE (strlen (module->name) + 1, 4);
if (module->shared_library)
- size += strlen (module->shared_library);
+ size += ALIGN_VALUE (strlen (module->shared_library) + 1, 4);
if (dependencies != NULL)
- size += strlen (dependencies);
+ size += ALIGN_VALUE (strlen (dependencies) + 1, 4);
+ if (module->c_prefix != NULL)
+ size += ALIGN_VALUE (strlen (module->c_prefix) + 1, 4);
g_message ("allocating %d bytes (%d header, %d directory, %d entries)\n",
size, header_size, dir_size, size - header_size - dir_size);
@@ -250,6 +254,9 @@ g_ir_module_build_typelib (GIrModule *module,
header->n_local_entries = n_local_entries;
header->n_attributes = 0;
header->attributes = 0; /* filled in later */
+ /* NOTE: When writing strings to the typelib here, you should also update
+ * the size calculations above.
+ */
if (dependencies != NULL)
header->dependencies = write_string (dependencies, strings, data, &header_size);
else
@@ -260,6 +267,10 @@ g_ir_module_build_typelib (GIrModule *module,
header->shared_library = (module->shared_library?
write_string (module->shared_library, strings, data, &header_size)
: 0);
+ if (module->c_prefix != NULL)
+ header->c_prefix = write_string (module->c_prefix, strings, data, &header_size);
+ else
+ header->c_prefix = 0;
header->directory = ALIGN_VALUE (header_size, 4);
header->entry_blob_size = sizeof (DirEntry);
header->function_blob_size = sizeof (FunctionBlob);
diff --git a/girepository/girmodule.h b/girepository/girmodule.h
index c658e179..5a558c35 100644
--- a/girepository/girmodule.h
+++ b/girepository/girmodule.h
@@ -34,6 +34,7 @@ struct _GIrModule
gchar *name;
gchar *version;
gchar *shared_library;
+ gchar *c_prefix;
GList *dependencies;
GList *entries;
@@ -50,7 +51,8 @@ struct _GIrModule
GIrModule *g_ir_module_new (const gchar *name,
const gchar *nsversion,
- const gchar *module_filename);
+ const gchar *module_filename,
+ const gchar *c_prefix);
void g_ir_module_free (GIrModule *module);
void g_ir_module_add_include_module (GIrModule *module,
diff --git a/girepository/girparser.c b/girepository/girparser.c
index 9afd8585..7727d230 100644
--- a/girepository/girparser.c
+++ b/girepository/girparser.c
@@ -88,6 +88,7 @@ struct _ParseContext
GHashTable *disguised_structures;
const char *namespace;
+ const char *c_prefix;
GIrModule *current_module;
GSList *node_stack;
GIrNode *current_typed;
@@ -2547,7 +2548,7 @@ start_element_handler (GMarkupParseContext *context,
case 'n':
if (strcmp (element_name, "namespace") == 0 && ctx->state == STATE_REPOSITORY)
{
- const gchar *name, *version, *shared_library;
+ const gchar *name, *version, *shared_library, *cprefix;
if (ctx->current_module != NULL)
{
@@ -2561,6 +2562,7 @@ start_element_handler (GMarkupParseContext *context,
name = find_attribute ("name", attribute_names, attribute_values);
version = find_attribute ("version", attribute_names, attribute_values);
shared_library = find_attribute ("shared-library", attribute_names, attribute_values);
+ cprefix = find_attribute ("c:prefix", attribute_names, attribute_values);
if (name == NULL)
MISSING_ATTRIBUTE (context, error, element_name, "name");
@@ -2577,7 +2579,7 @@ start_element_handler (GMarkupParseContext *context,
"<namespace/> name element '%s' doesn't match file name '%s'",
name, ctx->namespace);
- ctx->current_module = g_ir_module_new (name, version, shared_library);
+ ctx->current_module = g_ir_module_new (name, version, shared_library, cprefix);
ctx->current_module->aliases = ctx->aliases;
ctx->aliases = NULL;
diff --git a/girepository/gtypelib.c b/girepository/gtypelib.c
index a578c67d..64138aa0 100644
--- a/girepository/gtypelib.c
+++ b/girepository/gtypelib.c
@@ -161,7 +161,7 @@ g_typelib_check_sanity (void)
* Everything else in the code however should be using sizeof().
*/
- CHECK_SIZE (Header, 108);
+ CHECK_SIZE (Header, 112);
CHECK_SIZE (DirEntry, 12);
CHECK_SIZE (SimpleTypeBlob, 4);
CHECK_SIZE (ArgBlob, 16);
diff --git a/girepository/gtypelib.h b/girepository/gtypelib.h
index f6ad8c97..d4afa890 100644
--- a/girepository/gtypelib.h
+++ b/girepository/gtypelib.h
@@ -247,6 +247,7 @@ typedef struct {
guint32 namespace;
guint32 nsversion;
guint32 shared_library;
+ guint32 c_prefix;
guint16 entry_blob_size;
guint16 function_blob_size;
diff --git a/tests/scanner/BarApp-1.0-expected.tgir b/tests/scanner/BarApp-1.0-expected.tgir
index 20173cb9..45ceae06 100644
--- a/tests/scanner/BarApp-1.0-expected.tgir
+++ b/tests/scanner/BarApp-1.0-expected.tgir
@@ -5,7 +5,7 @@
xmlns:glib="http://www.gtk.org/introspection/glib/1.0">
<include name="GObject" version="2.0"/>
<include name="GLib" version="2.0"/>
- <namespace name="BarApp" version="1.0" shared-library="">
+ <namespace name="BarApp" version="1.0" shared-library="" c:prefix="Bar">
<class name="Baz" parent="GObject.Object" glib:type-struct="BazClass" glib:type-name="BarBaz" glib:get-type="bar_baz_get_type">
<field name="parent_instance">
<type name="GObject.Object"/>
diff --git a/tests/scanner/GtkFrob-1.0-expected.tgir b/tests/scanner/GtkFrob-1.0-expected.tgir
index 85c527d6..0d101be3 100644
--- a/tests/scanner/GtkFrob-1.0-expected.tgir
+++ b/tests/scanner/GtkFrob-1.0-expected.tgir
@@ -5,7 +5,7 @@
xmlns:glib="http://www.gtk.org/introspection/glib/1.0">
<include name="GObject" version="2.0"/>
<include name="GLib" version="2.0"/>
- <namespace name="GtkFrob" version="1.0" shared-library="gtkfrob">
+ <namespace name="GtkFrob" version="1.0" shared-library="gtkfrob" c:prefix="Gtk">
<function name="language_manager_get_default" c:identifier="gtk_frob_language_manager_get_default">
<return-value transfer-ownership="none">
<type name="none"/>
diff --git a/tests/scanner/annotation-1.0-expected.tgir b/tests/scanner/annotation-1.0-expected.tgir
index 99c3d260..3629d5ff 100644
--- a/tests/scanner/annotation-1.0-expected.tgir
+++ b/tests/scanner/annotation-1.0-expected.tgir
@@ -6,7 +6,7 @@
<include name="utility" version="1.0"/>
<include name="GObject" version="2.0"/>
<include name="GLib" version="2.0"/>
- <namespace name="annotation" version="1.0" shared-library="annotation">
+ <namespace name="annotation" version="1.0" shared-library="annotation" c:prefix="annotation">
<callback name="Callback">
<return-value transfer-ownership="none">
<type name="int"/>
diff --git a/tests/scanner/drawable-1.0-expected.tgir b/tests/scanner/drawable-1.0-expected.tgir
index 2c939612..618cf3af 100644
--- a/tests/scanner/drawable-1.0-expected.tgir
+++ b/tests/scanner/drawable-1.0-expected.tgir
@@ -6,7 +6,7 @@
<include name="utility" version="1.0"/>
<include name="GObject" version="2.0"/>
<include name="GLib" version="2.0"/>
- <namespace name="drawable" version="1.0" shared-library="drawable">
+ <namespace name="drawable" version="1.0" shared-library="drawable" c:prefix="drawable">
<class name="TestDrawable" parent="GObject.Object" glib:type-struct="TestDrawableClass" abstract="1" glib:type-name="TestDrawable" glib:get-type="test_drawable_get_type">
<field name="parent_instance">
<type name="GObject.Object"/>
diff --git a/tests/scanner/foo-1.0-expected.tgir b/tests/scanner/foo-1.0-expected.tgir
index bd94ed38..9a43eccb 100644
--- a/tests/scanner/foo-1.0-expected.tgir
+++ b/tests/scanner/foo-1.0-expected.tgir
@@ -6,7 +6,7 @@
<include name="utility" version="1.0"/>
<include name="GObject" version="2.0"/>
<include name="GLib" version="2.0"/>
- <namespace name="foo" version="1.0" shared-library="foo">
+ <namespace name="foo" version="1.0" shared-library="foo" c:prefix="foo">
<enumeration name="ASingle">
<member name="some_single_enum" value="0"/>
</enumeration>
diff --git a/tests/scanner/utility-1.0-expected.tgir b/tests/scanner/utility-1.0-expected.tgir
index dfd2aa80..2a30f850 100644
--- a/tests/scanner/utility-1.0-expected.tgir
+++ b/tests/scanner/utility-1.0-expected.tgir
@@ -5,7 +5,7 @@
xmlns:glib="http://www.gtk.org/introspection/glib/1.0">
<include name="GObject" version="2.0"/>
<include name="GLib" version="2.0"/>
- <namespace name="utility" version="1.0" shared-library="utility">
+ <namespace name="utility" version="1.0" shared-library="utility" c:prefix="utility">
<union name="Byte">
<field name="value" writable="1">
<type name="uint8"/>
diff --git a/tools/generate.c b/tools/generate.c
index 48d7dfb6..f8767218 100644
--- a/tools/generate.c
+++ b/tools/generate.c
@@ -1282,16 +1282,20 @@ write_repository (const char *namespace,
if (TRUE)
{
const gchar *shared_library;
+ const gchar *c_prefix;
const char *ns = namespace;
const char *version;
version = g_irepository_get_version (repository, ns);
shared_library = g_irepository_get_shared_library (repository, ns);
+ c_prefix = g_irepository_get_c_prefix (repository, ns);
xml_start_element (xml, "namespace");
xml_printf (xml, " name=\"%s\" version=\"%s\"", ns, version);
if (shared_library)
xml_printf (xml, " shared-library=\"%s\"", shared_library);
+ if (c_prefix)
+ xml_printf (xml, " c:prefix=\"%s\"", c_prefix);
for (j = 0; j < g_irepository_get_n_infos (repository, ns); j++)
{