X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gio%2Fgdbusintrospection.c;h=6d3ff93ead7224c5e4477e3a0cfc3cea1e132baa;hb=2a53b4d0e2c98a14aedf31e38f0ad1fb2e8fe26f;hp=56cfbbb5b13801b160a243dcc32a8b867c0acb9a;hpb=37c4fcb36abedfd7896ef70eaec75bba33a0331f;p=platform%2Fupstream%2Fglib.git
diff --git a/gio/gdbusintrospection.c b/gio/gdbusintrospection.c
index 56cfbbb..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,7 +26,6 @@
#include "gdbusintrospection.h"
#include "glibintl.h"
-#include "gioalias.h"
/**
* SECTION:gdbusintrospection
@@ -40,27 +37,14 @@
* 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().
*
@@ -1839,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);
@@ -1849,6 +1800,9 @@ g_dbus_node_info_new_for_xml (const gchar *xml_data,
error))
goto out;
+ 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,20 +1838,20 @@ 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;
@@ -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"