X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gio%2Fgdbusintrospection.c;h=6d3ff93ead7224c5e4477e3a0cfc3cea1e132baa;hb=25990eb2b6da94e1d03631eab8a952ef84cb9986;hp=c1c4d35c23fe9c0a5c98a8270aad0305d3f28453;hpb=6223341cacc7dfa34a8d60ec1b4828382dee6d07;p=platform%2Fupstream%2Fglib.git diff --git a/gio/gdbusintrospection.c b/gio/gdbusintrospection.c index c1c4d35..6d3ff93 100644 --- a/gio/gdbusintrospection.c +++ b/gio/gdbusintrospection.c @@ -13,9 +13,7 @@ * 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. + * Public License along with this library; if not, see . * * Author: David Zeuthen */ @@ -28,39 +26,25 @@ #include "gdbusintrospection.h" #include "glibintl.h" -#include "gioalias.h" /** * SECTION:gdbusintrospection - * @title: Introspection XML - * @short_description: Parse and Generate Introspection XML + * @title: D-Bus Introspection Data + * @short_description: Node and interface description data structures * @include: gio/gio.h * * Various data structures and convenience routines to parse and * generate D-Bus introspection XML. Introspection information is * used when registering objects with g_dbus_connection_register_object(). * - * The format of D-BUs introspection XML is specified in the - * D-Bus specification. + * The format of D-Bus introspection XML is specified in the + * [D-Bus specification](http://dbus.freedesktop.org/doc/dbus-specification.html#introspection-format) */ /* ---------------------------------------------------------------------------------------------------- */ -/* See also https://bugzilla.gnome.org/show_bug.cgi?id=449565 ... */ -#define _MY_DEFINE_BOXED_TYPE(TypeName, type_name) \ - GType \ - type_name##_get_type (void) \ - { \ - static volatile gsize type_volatile = 0; \ - if (g_once_init_enter (&type_volatile)) \ - { \ - GType type = g_boxed_type_register_static (g_intern_static_string (#TypeName), \ - (GBoxedCopyFunc) type_name##_ref, \ - (GBoxedFreeFunc) type_name##_unref); \ - g_once_init_leave (&type_volatile, type); \ - } \ - return (GType) type_volatile; \ - } +#define _MY_DEFINE_BOXED_TYPE(TypeName, type_name) \ + G_DEFINE_BOXED_TYPE (TypeName, type_name, type_name##_ref, type_name##_unref) _MY_DEFINE_BOXED_TYPE (GDBusNodeInfo, g_dbus_node_info); _MY_DEFINE_BOXED_TYPE (GDBusInterfaceInfo, g_dbus_interface_info); @@ -434,10 +418,10 @@ g_dbus_node_info_unref (GDBusNodeInfo *info) /* ---------------------------------------------------------------------------------------------------- */ static void -g_dbus_annotation_info_set (ParseData *data, - GDBusAnnotationInfo *info, - const gchar *key, - const gchar *value, +g_dbus_annotation_info_set (ParseData *data, + GDBusAnnotationInfo *info, + const gchar *key, + const gchar *value, GDBusAnnotationInfo **embedded_annotations) { info->ref_count = 1; @@ -476,9 +460,7 @@ static void g_dbus_method_info_set (ParseData *data, GDBusMethodInfo *info, const gchar *name, - guint in_num_args, GDBusArgInfo **in_args, - guint out_num_args, GDBusArgInfo **out_args, GDBusAnnotationInfo **annotations) { @@ -487,17 +469,11 @@ g_dbus_method_info_set (ParseData *data, if (name != NULL) info->name = g_strdup (name); - if (in_num_args != 0) - { - //info->in_num_args = in_num_args; - info->in_args = in_args; - } + if (in_args != NULL) + info->in_args = in_args; - if (out_num_args != 0) - { - //info->out_num_args = out_num_args; - info->out_args = out_args; - } + if (out_args != NULL) + info->out_args = out_args; if (annotations != NULL) info->annotations = annotations; @@ -507,7 +483,6 @@ static void g_dbus_signal_info_set (ParseData *data, GDBusSignalInfo *info, const gchar *name, - guint num_args, GDBusArgInfo **args, GDBusAnnotationInfo **annotations) { @@ -516,16 +491,11 @@ g_dbus_signal_info_set (ParseData *data, if (name != NULL) info->name = g_strdup (name); - if (num_args != 0) - { - //info->num_args = num_args; - info->args = args; - } + if (args != NULL) + info->args = args; if (annotations != NULL) - { - info->annotations = annotations; - } + info->annotations = annotations; } static void @@ -545,66 +515,44 @@ g_dbus_property_info_set (ParseData *data, info->flags = flags; if (signature != NULL) - { - info->signature = g_strdup (signature); - } + info->signature = g_strdup (signature); if (annotations != NULL) - { - info->annotations = annotations; - } + info->annotations = annotations; } static void g_dbus_interface_info_set (ParseData *data, GDBusInterfaceInfo *info, const gchar *name, - guint num_methods, GDBusMethodInfo **methods, - guint num_signals, GDBusSignalInfo **signals, - guint num_properties, GDBusPropertyInfo **properties, GDBusAnnotationInfo **annotations) { info->ref_count = 1; if (name != NULL) - { - info->name = g_strdup (name); - } + info->name = g_strdup (name); - if (num_methods != 0) - { - //info->num_methods = num_methods; - info->methods = methods; - } + if (methods != NULL) + info->methods = methods; - if (num_signals != 0) - { - //info->num_signals = num_signals; - info->signals = signals; - } + if (signals != NULL) + info->signals = signals; - if (num_properties != 0) - { - //info->num_properties = num_properties; - info->properties = properties; - } + if (properties != NULL) + info->properties = properties; if (annotations != NULL) - { - info->annotations = annotations; - } + info->annotations = annotations; } static void g_dbus_node_info_set (ParseData *data, GDBusNodeInfo *info, const gchar *path, - guint num_interfaces, GDBusInterfaceInfo **interfaces, - guint num_nodes, GDBusNodeInfo **nodes, GDBusAnnotationInfo **annotations) { @@ -616,38 +564,32 @@ g_dbus_node_info_set (ParseData *data, /* TODO: relative / absolute path snafu */ } - if (num_interfaces != 0) - { - //info->num_interfaces = num_interfaces; - info->interfaces = interfaces; - } + if (interfaces != NULL) + info->interfaces = interfaces; - if (num_nodes != 0) - { - //info->num_nodes = num_nodes; - info->nodes = nodes; - } + if (nodes != NULL) + info->nodes = nodes; if (annotations != NULL) - { - info->annotations = annotations; - } - + info->annotations = annotations; } /* ---------------------------------------------------------------------------------------------------- */ static void -g_dbus_annotation_info_generate_xml (const GDBusAnnotationInfo *info, - guint indent, - GString *string_builder) +g_dbus_annotation_info_generate_xml (GDBusAnnotationInfo *info, + guint indent, + GString *string_builder) { + gchar *tmp; guint n; - g_string_append_printf (string_builder, "%*skey, - info->value); + tmp = g_markup_printf_escaped ("%*skey, + info->value); + g_string_append (string_builder, tmp); + g_free (tmp); if (info->annotations == NULL) { @@ -669,10 +611,10 @@ g_dbus_annotation_info_generate_xml (const GDBusAnnotationInfo *info, } static void -g_dbus_arg_info_generate_xml (const GDBusArgInfo *info, - guint indent, - const gchar *extra_attributes, - GString *string_builder) +g_dbus_arg_info_generate_xml (GDBusArgInfo *info, + guint indent, + const gchar *extra_attributes, + GString *string_builder) { guint n; @@ -705,9 +647,9 @@ g_dbus_arg_info_generate_xml (const GDBusArgInfo *info, } static void -g_dbus_method_info_generate_xml (const GDBusMethodInfo *info, - guint indent, - GString *string_builder) +g_dbus_method_info_generate_xml (GDBusMethodInfo *info, + guint indent, + GString *string_builder) { guint n; @@ -745,9 +687,9 @@ g_dbus_method_info_generate_xml (const GDBusMethodInfo *info, } static void -g_dbus_signal_info_generate_xml (const GDBusSignalInfo *info, - guint indent, - GString *string_builder) +g_dbus_signal_info_generate_xml (GDBusSignalInfo *info, + guint indent, + GString *string_builder) { guint n; @@ -779,9 +721,9 @@ g_dbus_signal_info_generate_xml (const GDBusSignalInfo *info, } static void -g_dbus_property_info_generate_xml (const GDBusPropertyInfo *info, - guint indent, - GString *string_builder) +g_dbus_property_info_generate_xml (GDBusPropertyInfo *info, + guint indent, + GString *string_builder) { guint n; const gchar *access_string; @@ -832,21 +774,21 @@ g_dbus_property_info_generate_xml (const GDBusPropertyInfo *info, * g_dbus_interface_info_generate_xml: * @info: A #GDBusNodeInfo * @indent: Indentation level. - * @string_builder: A #GString to to append XML data to. + * @string_builder: (out): A #GString to to append XML data to. * * Appends an XML representation of @info (and its children) to @string_builder. * * This function is typically used for generating introspection XML * documents at run-time for handling the - * org.freedesktop.DBus.Introspectable.Introspect + * `org.freedesktop.DBus.Introspectable.Introspect` * method. * * Since: 2.26 */ void -g_dbus_interface_info_generate_xml (const GDBusInterfaceInfo *info, - guint indent, - GString *string_builder) +g_dbus_interface_info_generate_xml (GDBusInterfaceInfo *info, + guint indent, + GString *string_builder) { guint n; @@ -881,19 +823,19 @@ g_dbus_interface_info_generate_xml (const GDBusInterfaceInfo *info, * g_dbus_node_info_generate_xml: * @info: A #GDBusNodeInfo. * @indent: Indentation level. - * @string_builder: A #GString to to append XML data to. + * @string_builder: (out): A #GString to to append XML data to. * * Appends an XML representation of @info (and its children) to @string_builder. * * This function is typically used for generating introspection XML documents at run-time for - * handling the org.freedesktop.DBus.Introspectable.Introspect method. + * handling the `org.freedesktop.DBus.Introspectable.Introspect` method. * * Since: 2.26 */ void -g_dbus_node_info_generate_xml (const GDBusNodeInfo *info, - guint indent, - GString *string_builder) +g_dbus_node_info_generate_xml (GDBusNodeInfo *info, + guint indent, + GString *string_builder) { guint n; @@ -1290,6 +1232,9 @@ parse_data_free (ParseData *data) parse_data_free_methods (data); parse_data_free_signals (data); parse_data_free_properties (data); + parse_data_free_interfaces (data); + parse_data_free_annotations (data); + parse_data_free_nodes (data); g_free (data); } @@ -1345,8 +1290,8 @@ parser_start_element (GMarkupParseContext *context, g_dbus_node_info_set (data, parse_data_get_node (data, TRUE), name, - 0, NULL, - 0, NULL, + NULL, + NULL, NULL); /* push the currently retrieved interfaces and nodes on the stack and prepare new arrays */ @@ -1376,15 +1321,17 @@ parser_start_element (GMarkupParseContext *context, attribute_values, error, G_MARKUP_COLLECT_STRING, "name", &name, + /* seen in the wild */ + G_MARKUP_COLLECT_STRING | G_MARKUP_COLLECT_OPTIONAL, "version", NULL, G_MARKUP_COLLECT_INVALID)) goto out; g_dbus_interface_info_set (data, parse_data_get_interface (data, TRUE), name, - 0, NULL, - 0, NULL, - 0, NULL, + NULL, + NULL, + NULL, NULL); } @@ -1405,14 +1352,16 @@ parser_start_element (GMarkupParseContext *context, attribute_values, error, G_MARKUP_COLLECT_STRING, "name", &name, + /* seen in the wild */ + G_MARKUP_COLLECT_STRING | G_MARKUP_COLLECT_OPTIONAL, "version", NULL, G_MARKUP_COLLECT_INVALID)) goto out; g_dbus_method_info_set (data, parse_data_get_method (data, TRUE), name, - 0, NULL, - 0, NULL, + NULL, + NULL, NULL); data->num_args = 0; @@ -1441,7 +1390,7 @@ parser_start_element (GMarkupParseContext *context, g_dbus_signal_info_set (data, parse_data_get_signal (data, TRUE), name, - 0, NULL, + NULL, NULL); data->num_args = 0; @@ -1522,7 +1471,10 @@ parser_start_element (GMarkupParseContext *context, G_MARKUP_COLLECT_INVALID)) goto out; - is_in = FALSE; + if (strcmp (stack->next->data, "method") == 0) + is_in = TRUE; + else + is_in = FALSE; if (direction != NULL) { if (strcmp (direction, "in") == 0) @@ -1671,9 +1623,7 @@ parser_end_element (GMarkupParseContext *context, g_dbus_node_info_set (data, parse_data_get_node (data, FALSE), NULL, - num_interfaces, interfaces, - num_nodes, nodes, steal_annotations (data)); @@ -1694,11 +1644,8 @@ parser_end_element (GMarkupParseContext *context, g_dbus_interface_info_set (data, parse_data_get_interface (data, FALSE), NULL, - num_methods, methods, - num_signals, signals, - num_properties, properties, steal_annotations (data)); @@ -1716,9 +1663,7 @@ parser_end_element (GMarkupParseContext *context, g_dbus_method_info_set (data, parse_data_get_method (data, FALSE), NULL, - in_num_args, in_args, - out_num_args, out_args, steal_annotations (data)); } @@ -1732,7 +1677,6 @@ parser_end_element (GMarkupParseContext *context, g_dbus_signal_info_set (data, parse_data_get_signal (data, FALSE), NULL, - num_args, args, steal_annotations (data)); } @@ -1812,6 +1756,13 @@ parser_error (GMarkupParseContext *context, * * Parses @xml_data and returns a #GDBusNodeInfo representing the data. * + * The introspection XML must contain exactly one top-level + * element. + * + * Note that this routine is using a + * [GMarkup][glib-Simple-XML-Subset-Parser.description]-based + * parser that only accepts a subset of valid XML documents. + * * Returns: A #GDBusNodeInfo structure or %NULL if @error is set. Free * with g_dbus_node_info_unref(). * @@ -1826,6 +1777,7 @@ g_dbus_node_info_new_for_xml (const gchar *xml_data, GMarkupParser *parser; guint num_nodes; ParseData *data; + GDBusNodeInfo **ughret; ret = NULL; parser = NULL; @@ -1838,7 +1790,7 @@ g_dbus_node_info_new_for_xml (const gchar *xml_data, data = parse_data_new (); context = g_markup_parse_context_new (parser, - 0, + G_MARKUP_IGNORE_QUALIFIED, data, (GDestroyNotify) parse_data_free); @@ -1848,7 +1800,9 @@ g_dbus_node_info_new_for_xml (const gchar *xml_data, error)) goto out; - GDBusNodeInfo **ughret; + if (!g_markup_parse_context_end_parse (context, error)) + goto out; + ughret = parse_data_steal_nodes (data, &num_nodes); if (num_nodes != 1) @@ -1864,19 +1818,16 @@ g_dbus_node_info_new_for_xml (const gchar *xml_data, /* clean up */ for (n = 0; n < num_nodes; n++) { - for (n = 0; n < num_nodes; n++) - g_dbus_node_info_unref (&(ret[n])); + g_dbus_node_info_unref (ughret[n]); + ughret[n] = NULL; } - g_free (ret); - ret = NULL; } ret = ughret[0]; g_free (ughret); out: - if (parser != NULL) - g_free (parser); + g_free (parser); if (context != NULL) g_markup_parse_context_free (context); @@ -1887,26 +1838,26 @@ g_dbus_node_info_new_for_xml (const gchar *xml_data, /** * g_dbus_annotation_info_lookup: - * @annotations: A %NULL-terminated array of annotations or %NULL. + * @annotations: (array zero-terminated=1) (allow-none): A %NULL-terminated array of annotations or %NULL. * @name: The name of the annotation to look up. * * Looks up the value of an annotation. * - * This cost of this function is O(n) in number of annotations. + * The cost of this function is O(n) in number of annotations. * * Returns: The value or %NULL if not found. Do not free, it is owned by @annotations. * * Since: 2.26 */ const gchar * -g_dbus_annotation_info_lookup (const GDBusAnnotationInfo **annotations, - const gchar *name) +g_dbus_annotation_info_lookup (GDBusAnnotationInfo **annotations, + const gchar *name) { guint n; const gchar *ret; ret = NULL; - for (n = 0; annotations != NULL && annotations[n]->key != NULL; n++) + for (n = 0; annotations != NULL && annotations[n] != NULL; n++) { if (g_strcmp0 (annotations[n]->key, name) == 0) { @@ -1921,6 +1872,37 @@ g_dbus_annotation_info_lookup (const GDBusAnnotationInfo **annotations, /* ---------------------------------------------------------------------------------------------------- */ +G_LOCK_DEFINE_STATIC (info_cache_lock); + +typedef struct +{ + gint use_count; + + /* gchar* -> GDBusMethodInfo* */ + GHashTable *method_name_to_data; + + /* gchar* -> GDBusMethodInfo* */ + GHashTable *signal_name_to_data; + + /* gchar* -> GDBusMethodInfo* */ + GHashTable *property_name_to_data; +} InfoCacheEntry; + +static void +info_cache_free (InfoCacheEntry *cache) +{ + g_assert (cache->use_count == 0); + g_hash_table_unref (cache->method_name_to_data); + g_hash_table_unref (cache->signal_name_to_data); + g_hash_table_unref (cache->property_name_to_data); + g_slice_free (InfoCacheEntry, cache); +} + +/* maps from GDBusInterfaceInfo* to InfoCacheEntry* */ +static GHashTable *info_cache = NULL; + +/* ---------------------------------------------------------------------------------------------------- */ + /** * g_dbus_interface_info_lookup_method: * @info: A #GDBusInterfaceInfo. @@ -1928,22 +1910,37 @@ g_dbus_annotation_info_lookup (const GDBusAnnotationInfo **annotations, * * Looks up information about a method. * - * This cost of this function is O(n) in number of methods. + * The cost of this function is O(n) in number of methods unless + * g_dbus_interface_info_cache_build() has been used on @info. * - * Returns: A #GDBusMethodInfo or %NULL if not found. Do not free, it is owned by @info. + * Returns: (transfer none): A #GDBusMethodInfo or %NULL if not found. Do not free, it is owned by @info. * * Since: 2.26 */ -const GDBusMethodInfo * -g_dbus_interface_info_lookup_method (const GDBusInterfaceInfo *info, - const gchar *name) +GDBusMethodInfo * +g_dbus_interface_info_lookup_method (GDBusInterfaceInfo *info, + const gchar *name) { guint n; - const GDBusMethodInfo *result; + GDBusMethodInfo *result; + + G_LOCK (info_cache_lock); + if (G_LIKELY (info_cache != NULL)) + { + InfoCacheEntry *cache; + cache = g_hash_table_lookup (info_cache, info); + if (G_LIKELY (cache != NULL)) + { + result = g_hash_table_lookup (cache->method_name_to_data, name); + G_UNLOCK (info_cache_lock); + goto out; + } + } + G_UNLOCK (info_cache_lock); for (n = 0; info->methods != NULL && info->methods[n] != NULL; n++) { - const GDBusMethodInfo *i = info->methods[n]; + GDBusMethodInfo *i = info->methods[n]; if (g_strcmp0 (i->name, name) == 0) { @@ -1967,22 +1964,37 @@ g_dbus_interface_info_lookup_method (const GDBusInterfaceInfo *info, * * Looks up information about a signal. * - * This cost of this function is O(n) in number of signals. + * The cost of this function is O(n) in number of signals unless + * g_dbus_interface_info_cache_build() has been used on @info. * - * Returns: A #GDBusSignalInfo or %NULL if not found. Do not free, it is owned by @info. + * Returns: (transfer none): A #GDBusSignalInfo or %NULL if not found. Do not free, it is owned by @info. * * Since: 2.26 */ -const GDBusSignalInfo * -g_dbus_interface_info_lookup_signal (const GDBusInterfaceInfo *info, - const gchar *name) +GDBusSignalInfo * +g_dbus_interface_info_lookup_signal (GDBusInterfaceInfo *info, + const gchar *name) { guint n; - const GDBusSignalInfo *result; + GDBusSignalInfo *result; + + G_LOCK (info_cache_lock); + if (G_LIKELY (info_cache != NULL)) + { + InfoCacheEntry *cache; + cache = g_hash_table_lookup (info_cache, info); + if (G_LIKELY (cache != NULL)) + { + result = g_hash_table_lookup (cache->signal_name_to_data, name); + G_UNLOCK (info_cache_lock); + goto out; + } + } + G_UNLOCK (info_cache_lock); for (n = 0; info->signals != NULL && info->signals[n] != NULL; n++) { - const GDBusSignalInfo *i = info->signals[n]; + GDBusSignalInfo *i = info->signals[n]; if (g_strcmp0 (i->name, name) == 0) { @@ -2006,22 +2018,37 @@ g_dbus_interface_info_lookup_signal (const GDBusInterfaceInfo *info, * * Looks up information about a property. * - * This cost of this function is O(n) in number of properties. + * The cost of this function is O(n) in number of properties unless + * g_dbus_interface_info_cache_build() has been used on @info. * - * Returns: A #GDBusPropertyInfo or %NULL if not found. Do not free, it is owned by @info. + * Returns: (transfer none): A #GDBusPropertyInfo or %NULL if not found. Do not free, it is owned by @info. * * Since: 2.26 */ -const GDBusPropertyInfo * -g_dbus_interface_info_lookup_property (const GDBusInterfaceInfo *info, - const gchar *name) +GDBusPropertyInfo * +g_dbus_interface_info_lookup_property (GDBusInterfaceInfo *info, + const gchar *name) { guint n; - const GDBusPropertyInfo *result; + GDBusPropertyInfo *result; + + G_LOCK (info_cache_lock); + if (G_LIKELY (info_cache != NULL)) + { + InfoCacheEntry *cache; + cache = g_hash_table_lookup (info_cache, info); + if (G_LIKELY (cache != NULL)) + { + result = g_hash_table_lookup (cache->property_name_to_data, name); + G_UNLOCK (info_cache_lock); + goto out; + } + } + G_UNLOCK (info_cache_lock); for (n = 0; info->properties != NULL && info->properties[n] != NULL; n++) { - const GDBusPropertyInfo *i = info->properties[n]; + GDBusPropertyInfo *i = info->properties[n]; if (g_strcmp0 (i->name, name) == 0) { @@ -2039,28 +2066,117 @@ g_dbus_interface_info_lookup_property (const GDBusInterfaceInfo *info, /* ---------------------------------------------------------------------------------------------------- */ /** + * g_dbus_interface_info_cache_build: + * @info: A #GDBusInterfaceInfo. + * + * Builds a lookup-cache to speed up + * g_dbus_interface_info_lookup_method(), + * g_dbus_interface_info_lookup_signal() and + * g_dbus_interface_info_lookup_property(). + * + * If this has already been called with @info, the existing cache is + * used and its use count is increased. + * + * Note that @info cannot be modified until + * g_dbus_interface_info_cache_release() is called. + * + * Since: 2.30 + */ +void +g_dbus_interface_info_cache_build (GDBusInterfaceInfo *info) +{ + InfoCacheEntry *cache; + guint n; + + G_LOCK (info_cache_lock); + if (info_cache == NULL) + info_cache = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) info_cache_free); + cache = g_hash_table_lookup (info_cache, info); + if (cache != NULL) + { + cache->use_count += 1; + goto out; + } + cache = g_slice_new0 (InfoCacheEntry); + cache->use_count = 1; + cache->method_name_to_data = g_hash_table_new (g_str_hash, g_str_equal); + cache->signal_name_to_data = g_hash_table_new (g_str_hash, g_str_equal); + cache->property_name_to_data = g_hash_table_new (g_str_hash, g_str_equal); + for (n = 0; info->methods != NULL && info->methods[n] != NULL; n++) + g_hash_table_insert (cache->method_name_to_data, info->methods[n]->name, info->methods[n]); + for (n = 0; info->signals != NULL && info->signals[n] != NULL; n++) + g_hash_table_insert (cache->signal_name_to_data, info->signals[n]->name, info->signals[n]); + for (n = 0; info->properties != NULL && info->properties[n] != NULL; n++) + g_hash_table_insert (cache->property_name_to_data, info->properties[n]->name, info->properties[n]); + g_hash_table_insert (info_cache, info, cache); + out: + G_UNLOCK (info_cache_lock); +} + +/** + * g_dbus_interface_info_cache_release: + * @info: A GDBusInterfaceInfo + * + * Decrements the usage count for the cache for @info built by + * g_dbus_interface_info_cache_build() (if any) and frees the + * resources used by the cache if the usage count drops to zero. + * + * Since: 2.30 + */ +void +g_dbus_interface_info_cache_release (GDBusInterfaceInfo *info) +{ + InfoCacheEntry *cache; + + G_LOCK (info_cache_lock); + if (G_UNLIKELY (info_cache == NULL)) + { + g_warning ("%s called for interface %s but there is no cache", info->name, G_STRFUNC); + goto out; + } + + cache = g_hash_table_lookup (info_cache, info); + if (G_UNLIKELY (cache == NULL)) + { + g_warning ("%s called for interface %s but there is no cache entry", info->name, G_STRFUNC); + goto out; + } + cache->use_count -= 1; + if (cache->use_count == 0) + { + g_hash_table_remove (info_cache, info); + /* could nuke info_cache itself if empty */ + } + out: + G_UNLOCK (info_cache_lock); +} + + +/* ---------------------------------------------------------------------------------------------------- */ + +/** * g_dbus_node_info_lookup_interface: * @info: A #GDBusNodeInfo. * @name: A D-Bus interface name. * * Looks up information about an interface. * - * This cost of this function is O(n) in number of interfaces. + * The cost of this function is O(n) in number of interfaces. * - * Returns: A #GDBusInterfaceInfo or %NULL if not found. Do not free, it is owned by @info. + * Returns: (transfer none): A #GDBusInterfaceInfo or %NULL if not found. Do not free, it is owned by @info. * * Since: 2.26 */ -const GDBusInterfaceInfo * -g_dbus_node_info_lookup_interface (const GDBusNodeInfo *info, - const gchar *name) +GDBusInterfaceInfo * +g_dbus_node_info_lookup_interface (GDBusNodeInfo *info, + const gchar *name) { guint n; - const GDBusInterfaceInfo *result; + GDBusInterfaceInfo *result; for (n = 0; info->interfaces != NULL && info->interfaces[n] != NULL; n++) { - const GDBusInterfaceInfo *i = info->interfaces[n]; + GDBusInterfaceInfo *i = info->interfaces[n]; if (g_strcmp0 (i->name, name) == 0) { @@ -2074,6 +2190,3 @@ g_dbus_node_info_lookup_interface (const GDBusNodeInfo *info, out: return result; } - -#define __G_DBUS_INTROSPECTION_C__ -#include "gioaliasdef.c"