diff options
-rw-r--r-- | girepository/girepository.c | 76 | ||||
-rw-r--r-- | girepository/girepository.h | 2 | ||||
-rw-r--r-- | girepository/girmodule.c | 19 | ||||
-rw-r--r-- | girepository/girmodule.h | 4 | ||||
-rw-r--r-- | girepository/girparser.c | 6 | ||||
-rw-r--r-- | girepository/gtypelib.c | 2 | ||||
-rw-r--r-- | girepository/gtypelib.h | 1 | ||||
-rw-r--r-- | tests/scanner/BarApp-1.0-expected.tgir | 2 | ||||
-rw-r--r-- | tests/scanner/GtkFrob-1.0-expected.tgir | 2 | ||||
-rw-r--r-- | tests/scanner/annotation-1.0-expected.tgir | 2 | ||||
-rw-r--r-- | tests/scanner/drawable-1.0-expected.tgir | 2 | ||||
-rw-r--r-- | tests/scanner/foo-1.0-expected.tgir | 2 | ||||
-rw-r--r-- | tests/scanner/utility-1.0-expected.tgir | 2 | ||||
-rw-r--r-- | tools/generate.c | 4 |
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++) { |