1 /* GDBus - GLib D-Bus Library
3 * Copyright (C) 2008-2010 Red Hat, Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 * Author: David Zeuthen <davidz@redhat.com>
26 #include "gdbusintrospection.h"
31 * SECTION:gdbusintrospection
32 * @title: D-Bus Introspection Data
33 * @short_description: Node and interface description data structures
36 * Various data structures and convenience routines to parse and
37 * generate D-Bus introspection XML. Introspection information is
38 * used when registering objects with g_dbus_connection_register_object().
40 * The format of D-Bus introspection XML is specified in the
41 * [D-Bus specification](http://dbus.freedesktop.org/doc/dbus-specification.html#introspection-format)
44 /* ---------------------------------------------------------------------------------------------------- */
46 #define _MY_DEFINE_BOXED_TYPE(TypeName, type_name) \
47 G_DEFINE_BOXED_TYPE (TypeName, type_name, type_name##_ref, type_name##_unref)
49 _MY_DEFINE_BOXED_TYPE (GDBusNodeInfo
, g_dbus_node_info
)
50 _MY_DEFINE_BOXED_TYPE (GDBusInterfaceInfo
, g_dbus_interface_info
)
51 _MY_DEFINE_BOXED_TYPE (GDBusMethodInfo
, g_dbus_method_info
)
52 _MY_DEFINE_BOXED_TYPE (GDBusSignalInfo
, g_dbus_signal_info
)
53 _MY_DEFINE_BOXED_TYPE (GDBusPropertyInfo
, g_dbus_property_info
)
54 _MY_DEFINE_BOXED_TYPE (GDBusArgInfo
, g_dbus_arg_info
)
55 _MY_DEFINE_BOXED_TYPE (GDBusAnnotationInfo
, g_dbus_annotation_info
)
57 #undef _MY_DEFINE_BOXED_TYPE
59 /* ---------------------------------------------------------------------------------------------------- */
63 /* stuff we are currently collecting */
68 GPtrArray
*properties
;
69 GPtrArray
*interfaces
;
71 GPtrArray
*annotations
;
73 /* A list of GPtrArray's containing annotations */
74 GSList
*annotations_stack
;
76 /* A list of GPtrArray's containing interfaces */
77 GSList
*interfaces_stack
;
79 /* A list of GPtrArray's containing nodes */
82 /* Whether the direction was "in" for last parsed arg */
83 gboolean last_arg_was_in
;
85 /* Number of args currently being collected; used for assigning
86 * names to args without a "name" attribute
92 /* ---------------------------------------------------------------------------------------------------- */
95 * g_dbus_node_info_ref:
96 * @info: A #GDBusNodeInfo
98 * If @info is statically allocated does nothing. Otherwise increases
99 * the reference count.
101 * Returns: The same @info.
106 g_dbus_node_info_ref (GDBusNodeInfo
*info
)
108 if (info
->ref_count
== -1)
110 g_atomic_int_inc (&info
->ref_count
);
115 * g_dbus_interface_info_ref:
116 * @info: A #GDBusInterfaceInfo
118 * If @info is statically allocated does nothing. Otherwise increases
119 * the reference count.
121 * Returns: The same @info.
126 g_dbus_interface_info_ref (GDBusInterfaceInfo
*info
)
128 if (info
->ref_count
== -1)
130 g_atomic_int_inc (&info
->ref_count
);
135 * g_dbus_method_info_ref:
136 * @info: A #GDBusMethodInfo
138 * If @info is statically allocated does nothing. Otherwise increases
139 * the reference count.
141 * Returns: The same @info.
146 g_dbus_method_info_ref (GDBusMethodInfo
*info
)
148 if (info
->ref_count
== -1)
150 g_atomic_int_inc (&info
->ref_count
);
155 * g_dbus_signal_info_ref:
156 * @info: A #GDBusSignalInfo
158 * If @info is statically allocated does nothing. Otherwise increases
159 * the reference count.
161 * Returns: The same @info.
166 g_dbus_signal_info_ref (GDBusSignalInfo
*info
)
168 if (info
->ref_count
== -1)
170 g_atomic_int_inc (&info
->ref_count
);
175 * g_dbus_property_info_ref:
176 * @info: A #GDBusPropertyInfo
178 * If @info is statically allocated does nothing. Otherwise increases
179 * the reference count.
181 * Returns: The same @info.
186 g_dbus_property_info_ref (GDBusPropertyInfo
*info
)
188 if (info
->ref_count
== -1)
190 g_atomic_int_inc (&info
->ref_count
);
195 * g_dbus_arg_info_ref:
196 * @info: A #GDBusArgInfo
198 * If @info is statically allocated does nothing. Otherwise increases
199 * the reference count.
201 * Returns: The same @info.
206 g_dbus_arg_info_ref (GDBusArgInfo
*info
)
208 if (info
->ref_count
== -1)
210 g_atomic_int_inc (&info
->ref_count
);
215 * g_dbus_annotation_info_ref:
216 * @info: A #GDBusNodeInfo
218 * If @info is statically allocated does nothing. Otherwise increases
219 * the reference count.
221 * Returns: The same @info.
225 GDBusAnnotationInfo
*
226 g_dbus_annotation_info_ref (GDBusAnnotationInfo
*info
)
228 if (info
->ref_count
== -1)
230 g_atomic_int_inc (&info
->ref_count
);
234 /* ---------------------------------------------------------------------------------------------------- */
237 free_null_terminated_array (gpointer array
, GDestroyNotify unref_func
)
243 for (n
= 0; p
[n
] != NULL
; n
++)
249 * g_dbus_annotation_info_unref:
250 * @info: A #GDBusAnnotationInfo.
252 * If @info is statically allocated, does nothing. Otherwise decreases
253 * the reference count of @info. When its reference count drops to 0,
254 * the memory used is freed.
259 g_dbus_annotation_info_unref (GDBusAnnotationInfo
*info
)
261 if (info
->ref_count
== -1)
263 if (g_atomic_int_dec_and_test (&info
->ref_count
))
266 g_free (info
->value
);
267 free_null_terminated_array (info
->annotations
, (GDestroyNotify
) g_dbus_annotation_info_unref
);
273 * g_dbus_arg_info_unref:
274 * @info: A #GDBusArgInfo.
276 * If @info is statically allocated, does nothing. Otherwise decreases
277 * the reference count of @info. When its reference count drops to 0,
278 * the memory used is freed.
283 g_dbus_arg_info_unref (GDBusArgInfo
*info
)
285 if (info
->ref_count
== -1)
287 if (g_atomic_int_dec_and_test (&info
->ref_count
))
290 g_free (info
->signature
);
291 free_null_terminated_array (info
->annotations
, (GDestroyNotify
) g_dbus_annotation_info_unref
);
297 * g_dbus_method_info_unref:
298 * @info: A #GDBusMethodInfo.
300 * If @info is statically allocated, does nothing. Otherwise decreases
301 * the reference count of @info. When its reference count drops to 0,
302 * the memory used is freed.
307 g_dbus_method_info_unref (GDBusMethodInfo
*info
)
309 if (info
->ref_count
== -1)
311 if (g_atomic_int_dec_and_test (&info
->ref_count
))
314 free_null_terminated_array (info
->in_args
, (GDestroyNotify
) g_dbus_arg_info_unref
);
315 free_null_terminated_array (info
->out_args
, (GDestroyNotify
) g_dbus_arg_info_unref
);
316 free_null_terminated_array (info
->annotations
, (GDestroyNotify
) g_dbus_annotation_info_unref
);
322 * g_dbus_signal_info_unref:
323 * @info: A #GDBusSignalInfo.
325 * If @info is statically allocated, does nothing. Otherwise decreases
326 * the reference count of @info. When its reference count drops to 0,
327 * the memory used is freed.
332 g_dbus_signal_info_unref (GDBusSignalInfo
*info
)
334 if (info
->ref_count
== -1)
336 if (g_atomic_int_dec_and_test (&info
->ref_count
))
339 free_null_terminated_array (info
->args
, (GDestroyNotify
) g_dbus_arg_info_unref
);
340 free_null_terminated_array (info
->annotations
, (GDestroyNotify
) g_dbus_annotation_info_unref
);
346 * g_dbus_property_info_unref:
347 * @info: A #GDBusPropertyInfo.
349 * If @info is statically allocated, does nothing. Otherwise decreases
350 * the reference count of @info. When its reference count drops to 0,
351 * the memory used is freed.
356 g_dbus_property_info_unref (GDBusPropertyInfo
*info
)
358 if (info
->ref_count
== -1)
360 if (g_atomic_int_dec_and_test (&info
->ref_count
))
363 g_free (info
->signature
);
364 free_null_terminated_array (info
->annotations
, (GDestroyNotify
) g_dbus_annotation_info_unref
);
370 * g_dbus_interface_info_unref:
371 * @info: A #GDBusInterfaceInfo.
373 * If @info is statically allocated, does nothing. Otherwise decreases
374 * the reference count of @info. When its reference count drops to 0,
375 * the memory used is freed.
380 g_dbus_interface_info_unref (GDBusInterfaceInfo
*info
)
382 if (info
->ref_count
== -1)
384 if (g_atomic_int_dec_and_test (&info
->ref_count
))
387 free_null_terminated_array (info
->methods
, (GDestroyNotify
) g_dbus_method_info_unref
);
388 free_null_terminated_array (info
->signals
, (GDestroyNotify
) g_dbus_signal_info_unref
);
389 free_null_terminated_array (info
->properties
, (GDestroyNotify
) g_dbus_property_info_unref
);
390 free_null_terminated_array (info
->annotations
, (GDestroyNotify
) g_dbus_annotation_info_unref
);
396 * g_dbus_node_info_unref:
397 * @info: A #GDBusNodeInfo.
399 * If @info is statically allocated, does nothing. Otherwise decreases
400 * the reference count of @info. When its reference count drops to 0,
401 * the memory used is freed.
406 g_dbus_node_info_unref (GDBusNodeInfo
*info
)
408 if (info
->ref_count
== -1)
410 if (g_atomic_int_dec_and_test (&info
->ref_count
))
413 free_null_terminated_array (info
->interfaces
, (GDestroyNotify
) g_dbus_interface_info_unref
);
414 free_null_terminated_array (info
->nodes
, (GDestroyNotify
) g_dbus_node_info_unref
);
415 free_null_terminated_array (info
->annotations
, (GDestroyNotify
) g_dbus_annotation_info_unref
);
420 /* ---------------------------------------------------------------------------------------------------- */
423 g_dbus_annotation_info_set (ParseData
*data
,
424 GDBusAnnotationInfo
*info
,
427 GDBusAnnotationInfo
**embedded_annotations
)
432 info
->key
= g_strdup (key
);
435 info
->value
= g_strdup (value
);
437 if (embedded_annotations
!= NULL
)
438 info
->annotations
= embedded_annotations
;
442 g_dbus_arg_info_set (ParseData
*data
,
445 const gchar
*signature
,
446 GDBusAnnotationInfo
**annotations
)
450 /* name may be NULL - TODO: compute name? */
452 info
->name
= g_strdup (name
);
454 if (signature
!= NULL
)
455 info
->signature
= g_strdup (signature
);
457 if (annotations
!= NULL
)
458 info
->annotations
= annotations
;
462 g_dbus_method_info_set (ParseData
*data
,
463 GDBusMethodInfo
*info
,
465 GDBusArgInfo
**in_args
,
466 GDBusArgInfo
**out_args
,
467 GDBusAnnotationInfo
**annotations
)
472 info
->name
= g_strdup (name
);
475 info
->in_args
= in_args
;
477 if (out_args
!= NULL
)
478 info
->out_args
= out_args
;
480 if (annotations
!= NULL
)
481 info
->annotations
= annotations
;
485 g_dbus_signal_info_set (ParseData
*data
,
486 GDBusSignalInfo
*info
,
489 GDBusAnnotationInfo
**annotations
)
494 info
->name
= g_strdup (name
);
499 if (annotations
!= NULL
)
500 info
->annotations
= annotations
;
504 g_dbus_property_info_set (ParseData
*data
,
505 GDBusPropertyInfo
*info
,
507 const gchar
*signature
,
508 GDBusPropertyInfoFlags flags
,
509 GDBusAnnotationInfo
**annotations
)
514 info
->name
= g_strdup (name
);
516 if (flags
!= G_DBUS_PROPERTY_INFO_FLAGS_NONE
)
519 if (signature
!= NULL
)
520 info
->signature
= g_strdup (signature
);
522 if (annotations
!= NULL
)
523 info
->annotations
= annotations
;
527 g_dbus_interface_info_set (ParseData
*data
,
528 GDBusInterfaceInfo
*info
,
530 GDBusMethodInfo
**methods
,
531 GDBusSignalInfo
**signals
,
532 GDBusPropertyInfo
**properties
,
533 GDBusAnnotationInfo
**annotations
)
538 info
->name
= g_strdup (name
);
541 info
->methods
= methods
;
544 info
->signals
= signals
;
546 if (properties
!= NULL
)
547 info
->properties
= properties
;
549 if (annotations
!= NULL
)
550 info
->annotations
= annotations
;
554 g_dbus_node_info_set (ParseData
*data
,
557 GDBusInterfaceInfo
**interfaces
,
558 GDBusNodeInfo
**nodes
,
559 GDBusAnnotationInfo
**annotations
)
565 info
->path
= g_strdup (path
);
566 /* TODO: relative / absolute path snafu */
569 if (interfaces
!= NULL
)
570 info
->interfaces
= interfaces
;
575 if (annotations
!= NULL
)
576 info
->annotations
= annotations
;
579 /* ---------------------------------------------------------------------------------------------------- */
582 g_dbus_annotation_info_generate_xml (GDBusAnnotationInfo
*info
,
584 GString
*string_builder
)
589 tmp
= g_markup_printf_escaped ("%*s<annotation name=\"%s\" value=\"%s\"",
593 g_string_append (string_builder
, tmp
);
596 if (info
->annotations
== NULL
)
598 g_string_append (string_builder
, "/>\n");
602 g_string_append (string_builder
, ">\n");
604 for (n
= 0; info
->annotations
!= NULL
&& info
->annotations
[n
] != NULL
; n
++)
605 g_dbus_annotation_info_generate_xml (info
->annotations
[n
],
609 g_string_append_printf (string_builder
, "%*s</annotation>\n",
616 g_dbus_arg_info_generate_xml (GDBusArgInfo
*info
,
618 const gchar
*extra_attributes
,
619 GString
*string_builder
)
623 g_string_append_printf (string_builder
, "%*s<arg type=\"%s\"",
627 if (info
->name
!= NULL
)
628 g_string_append_printf (string_builder
, " name=\"%s\"", info
->name
);
630 if (extra_attributes
!= NULL
)
631 g_string_append_printf (string_builder
, " %s", extra_attributes
);
633 if (info
->annotations
== NULL
)
635 g_string_append (string_builder
, "/>\n");
639 g_string_append (string_builder
, ">\n");
641 for (n
= 0; info
->annotations
!= NULL
&& info
->annotations
[n
] != NULL
; n
++)
642 g_dbus_annotation_info_generate_xml (info
->annotations
[n
],
646 g_string_append_printf (string_builder
, "%*s</arg>\n", indent
, "");
652 g_dbus_method_info_generate_xml (GDBusMethodInfo
*info
,
654 GString
*string_builder
)
658 g_string_append_printf (string_builder
, "%*s<method name=\"%s\"",
662 if (info
->annotations
== NULL
&& info
->in_args
== NULL
&& info
->out_args
== NULL
)
664 g_string_append (string_builder
, "/>\n");
668 g_string_append (string_builder
, ">\n");
670 for (n
= 0; info
->annotations
!= NULL
&& info
->annotations
[n
] != NULL
; n
++)
671 g_dbus_annotation_info_generate_xml (info
->annotations
[n
],
675 for (n
= 0; info
->in_args
!= NULL
&& info
->in_args
[n
] != NULL
; n
++)
676 g_dbus_arg_info_generate_xml (info
->in_args
[n
],
681 for (n
= 0; info
->out_args
!= NULL
&& info
->out_args
[n
] != NULL
; n
++)
682 g_dbus_arg_info_generate_xml (info
->out_args
[n
],
687 g_string_append_printf (string_builder
, "%*s</method>\n", indent
, "");
692 g_dbus_signal_info_generate_xml (GDBusSignalInfo
*info
,
694 GString
*string_builder
)
698 g_string_append_printf (string_builder
, "%*s<signal name=\"%s\"",
702 if (info
->annotations
== NULL
&& info
->args
== NULL
)
704 g_string_append (string_builder
, "/>\n");
708 g_string_append (string_builder
, ">\n");
710 for (n
= 0; info
->annotations
!= NULL
&& info
->annotations
[n
] != NULL
; n
++)
711 g_dbus_annotation_info_generate_xml (info
->annotations
[n
],
715 for (n
= 0; info
->args
!= NULL
&& info
->args
[n
] != NULL
; n
++)
716 g_dbus_arg_info_generate_xml (info
->args
[n
],
721 g_string_append_printf (string_builder
, "%*s</signal>\n", indent
, "");
726 g_dbus_property_info_generate_xml (GDBusPropertyInfo
*info
,
728 GString
*string_builder
)
731 const gchar
*access_string
;
733 if ((info
->flags
& G_DBUS_PROPERTY_INFO_FLAGS_READABLE
) &&
734 (info
->flags
& G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE
))
736 access_string
= "readwrite";
738 else if (info
->flags
& G_DBUS_PROPERTY_INFO_FLAGS_READABLE
)
740 access_string
= "read";
742 else if (info
->flags
& G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE
)
744 access_string
= "write";
748 g_assert_not_reached ();
751 g_string_append_printf (string_builder
, "%*s<property type=\"%s\" name=\"%s\" access=\"%s\"",
757 if (info
->annotations
== NULL
)
759 g_string_append (string_builder
, "/>\n");
763 g_string_append (string_builder
, ">\n");
765 for (n
= 0; info
->annotations
!= NULL
&& info
->annotations
[n
] != NULL
; n
++)
766 g_dbus_annotation_info_generate_xml (info
->annotations
[n
],
770 g_string_append_printf (string_builder
, "%*s</property>\n", indent
, "");
776 * g_dbus_interface_info_generate_xml:
777 * @info: A #GDBusNodeInfo
778 * @indent: Indentation level.
779 * @string_builder: A #GString to to append XML data to.
781 * Appends an XML representation of @info (and its children) to @string_builder.
783 * This function is typically used for generating introspection XML
784 * documents at run-time for handling the
785 * `org.freedesktop.DBus.Introspectable.Introspect`
791 g_dbus_interface_info_generate_xml (GDBusInterfaceInfo
*info
,
793 GString
*string_builder
)
797 g_string_append_printf (string_builder
, "%*s<interface name=\"%s\">\n",
801 for (n
= 0; info
->annotations
!= NULL
&& info
->annotations
[n
] != NULL
; n
++)
802 g_dbus_annotation_info_generate_xml (info
->annotations
[n
],
806 for (n
= 0; info
->methods
!= NULL
&& info
->methods
[n
] != NULL
; n
++)
807 g_dbus_method_info_generate_xml (info
->methods
[n
],
811 for (n
= 0; info
->signals
!= NULL
&& info
->signals
[n
] != NULL
; n
++)
812 g_dbus_signal_info_generate_xml (info
->signals
[n
],
816 for (n
= 0; info
->properties
!= NULL
&& info
->properties
[n
] != NULL
; n
++)
817 g_dbus_property_info_generate_xml (info
->properties
[n
],
821 g_string_append_printf (string_builder
, "%*s</interface>\n", indent
, "");
825 * g_dbus_node_info_generate_xml:
826 * @info: A #GDBusNodeInfo.
827 * @indent: Indentation level.
828 * @string_builder: A #GString to to append XML data to.
830 * Appends an XML representation of @info (and its children) to @string_builder.
832 * This function is typically used for generating introspection XML documents at run-time for
833 * handling the `org.freedesktop.DBus.Introspectable.Introspect` method.
838 g_dbus_node_info_generate_xml (GDBusNodeInfo
*info
,
840 GString
*string_builder
)
844 g_string_append_printf (string_builder
, "%*s<node", indent
, "");
845 if (info
->path
!= NULL
)
846 g_string_append_printf (string_builder
, " name=\"%s\"", info
->path
);
848 if (info
->interfaces
== NULL
&& info
->nodes
== NULL
&& info
->annotations
== NULL
)
850 g_string_append (string_builder
, "/>\n");
854 g_string_append (string_builder
, ">\n");
856 for (n
= 0; info
->annotations
!= NULL
&& info
->annotations
[n
] != NULL
; n
++)
857 g_dbus_annotation_info_generate_xml (info
->annotations
[n
],
861 for (n
= 0; info
->interfaces
!= NULL
&& info
->interfaces
[n
] != NULL
; n
++)
862 g_dbus_interface_info_generate_xml (info
->interfaces
[n
],
866 for (n
= 0; info
->nodes
!= NULL
&& info
->nodes
[n
] != NULL
; n
++)
867 g_dbus_node_info_generate_xml (info
->nodes
[n
],
871 g_string_append_printf (string_builder
, "%*s</node>\n", indent
, "");
875 /* ---------------------------------------------------------------------------------------------------- */
877 static GDBusAnnotationInfo
**
878 parse_data_steal_annotations (ParseData
*data
,
879 guint
*out_num_elements
)
881 GDBusAnnotationInfo
**ret
;
882 if (out_num_elements
!= NULL
)
883 *out_num_elements
= data
->annotations
->len
;
884 if (data
->annotations
== NULL
)
888 g_ptr_array_add (data
->annotations
, NULL
);
889 ret
= (GDBusAnnotationInfo
**) g_ptr_array_free (data
->annotations
, FALSE
);
891 data
->annotations
= g_ptr_array_new ();
895 static GDBusArgInfo
**
896 parse_data_steal_args (ParseData
*data
,
897 guint
*out_num_elements
)
900 if (out_num_elements
!= NULL
)
901 *out_num_elements
= data
->args
->len
;
902 if (data
->args
== NULL
)
906 g_ptr_array_add (data
->args
, NULL
);
907 ret
= (GDBusArgInfo
**) g_ptr_array_free (data
->args
, FALSE
);
909 data
->args
= g_ptr_array_new ();
913 static GDBusArgInfo
**
914 parse_data_steal_out_args (ParseData
*data
,
915 guint
*out_num_elements
)
918 if (out_num_elements
!= NULL
)
919 *out_num_elements
= data
->out_args
->len
;
920 if (data
->out_args
== NULL
)
924 g_ptr_array_add (data
->out_args
, NULL
);
925 ret
= (GDBusArgInfo
**) g_ptr_array_free (data
->out_args
, FALSE
);
927 data
->out_args
= g_ptr_array_new ();
931 static GDBusMethodInfo
**
932 parse_data_steal_methods (ParseData
*data
,
933 guint
*out_num_elements
)
935 GDBusMethodInfo
**ret
;
936 if (out_num_elements
!= NULL
)
937 *out_num_elements
= data
->methods
->len
;
938 if (data
->methods
== NULL
)
942 g_ptr_array_add (data
->methods
, NULL
);
943 ret
= (GDBusMethodInfo
**) g_ptr_array_free (data
->methods
, FALSE
);
945 data
->methods
= g_ptr_array_new ();
949 static GDBusSignalInfo
**
950 parse_data_steal_signals (ParseData
*data
,
951 guint
*out_num_elements
)
953 GDBusSignalInfo
**ret
;
954 if (out_num_elements
!= NULL
)
955 *out_num_elements
= data
->signals
->len
;
956 if (data
->signals
== NULL
)
960 g_ptr_array_add (data
->signals
, NULL
);
961 ret
= (GDBusSignalInfo
**) g_ptr_array_free (data
->signals
, FALSE
);
963 data
->signals
= g_ptr_array_new ();
967 static GDBusPropertyInfo
**
968 parse_data_steal_properties (ParseData
*data
,
969 guint
*out_num_elements
)
971 GDBusPropertyInfo
**ret
;
972 if (out_num_elements
!= NULL
)
973 *out_num_elements
= data
->properties
->len
;
974 if (data
->properties
== NULL
)
978 g_ptr_array_add (data
->properties
, NULL
);
979 ret
= (GDBusPropertyInfo
**) g_ptr_array_free (data
->properties
, FALSE
);
981 data
->properties
= g_ptr_array_new ();
985 static GDBusInterfaceInfo
**
986 parse_data_steal_interfaces (ParseData
*data
,
987 guint
*out_num_elements
)
989 GDBusInterfaceInfo
**ret
;
990 if (out_num_elements
!= NULL
)
991 *out_num_elements
= data
->interfaces
->len
;
992 if (data
->interfaces
== NULL
)
996 g_ptr_array_add (data
->interfaces
, NULL
);
997 ret
= (GDBusInterfaceInfo
**) g_ptr_array_free (data
->interfaces
, FALSE
);
999 data
->interfaces
= g_ptr_array_new ();
1003 static GDBusNodeInfo
**
1004 parse_data_steal_nodes (ParseData
*data
,
1005 guint
*out_num_elements
)
1007 GDBusNodeInfo
**ret
;
1008 if (out_num_elements
!= NULL
)
1009 *out_num_elements
= data
->nodes
->len
;
1010 if (data
->nodes
== NULL
)
1014 g_ptr_array_add (data
->nodes
, NULL
);
1015 ret
= (GDBusNodeInfo
**) g_ptr_array_free (data
->nodes
, FALSE
);
1017 data
->nodes
= g_ptr_array_new ();
1021 /* ---------------------------------------------------------------------------------------------------- */
1024 parse_data_free_annotations (ParseData
*data
)
1026 if (data
->annotations
== NULL
)
1028 g_ptr_array_foreach (data
->annotations
, (GFunc
) g_dbus_annotation_info_unref
, NULL
);
1029 g_ptr_array_free (data
->annotations
, TRUE
);
1030 data
->annotations
= NULL
;
1034 parse_data_free_args (ParseData
*data
)
1036 if (data
->args
== NULL
)
1038 g_ptr_array_foreach (data
->args
, (GFunc
) g_dbus_arg_info_unref
, NULL
);
1039 g_ptr_array_free (data
->args
, TRUE
);
1044 parse_data_free_out_args (ParseData
*data
)
1046 if (data
->out_args
== NULL
)
1048 g_ptr_array_foreach (data
->out_args
, (GFunc
) g_dbus_arg_info_unref
, NULL
);
1049 g_ptr_array_free (data
->out_args
, TRUE
);
1050 data
->out_args
= NULL
;
1054 parse_data_free_methods (ParseData
*data
)
1056 if (data
->methods
== NULL
)
1058 g_ptr_array_foreach (data
->methods
, (GFunc
) g_dbus_method_info_unref
, NULL
);
1059 g_ptr_array_free (data
->methods
, TRUE
);
1060 data
->methods
= NULL
;
1064 parse_data_free_signals (ParseData
*data
)
1066 if (data
->signals
== NULL
)
1068 g_ptr_array_foreach (data
->signals
, (GFunc
) g_dbus_signal_info_unref
, NULL
);
1069 g_ptr_array_free (data
->signals
, TRUE
);
1070 data
->signals
= NULL
;
1074 parse_data_free_properties (ParseData
*data
)
1076 if (data
->properties
== NULL
)
1078 g_ptr_array_foreach (data
->properties
, (GFunc
) g_dbus_property_info_unref
, NULL
);
1079 g_ptr_array_free (data
->properties
, TRUE
);
1080 data
->properties
= NULL
;
1084 parse_data_free_interfaces (ParseData
*data
)
1086 if (data
->interfaces
== NULL
)
1088 g_ptr_array_foreach (data
->interfaces
, (GFunc
) g_dbus_interface_info_unref
, NULL
);
1089 g_ptr_array_free (data
->interfaces
, TRUE
);
1090 data
->interfaces
= NULL
;
1094 parse_data_free_nodes (ParseData
*data
)
1096 if (data
->nodes
== NULL
)
1098 g_ptr_array_foreach (data
->nodes
, (GFunc
) g_dbus_node_info_unref
, NULL
);
1099 g_ptr_array_free (data
->nodes
, TRUE
);
1103 /* ---------------------------------------------------------------------------------------------------- */
1105 static GDBusAnnotationInfo
*
1106 parse_data_get_annotation (ParseData
*data
,
1107 gboolean create_new
)
1110 g_ptr_array_add (data
->annotations
, g_new0 (GDBusAnnotationInfo
, 1));
1111 return data
->annotations
->pdata
[data
->annotations
->len
- 1];
1114 static GDBusArgInfo
*
1115 parse_data_get_arg (ParseData
*data
,
1116 gboolean create_new
)
1119 g_ptr_array_add (data
->args
, g_new0 (GDBusArgInfo
, 1));
1120 return data
->args
->pdata
[data
->args
->len
- 1];
1123 static GDBusArgInfo
*
1124 parse_data_get_out_arg (ParseData
*data
,
1125 gboolean create_new
)
1128 g_ptr_array_add (data
->out_args
, g_new0 (GDBusArgInfo
, 1));
1129 return data
->out_args
->pdata
[data
->out_args
->len
- 1];
1132 static GDBusMethodInfo
*
1133 parse_data_get_method (ParseData
*data
,
1134 gboolean create_new
)
1137 g_ptr_array_add (data
->methods
, g_new0 (GDBusMethodInfo
, 1));
1138 return data
->methods
->pdata
[data
->methods
->len
- 1];
1141 static GDBusSignalInfo
*
1142 parse_data_get_signal (ParseData
*data
,
1143 gboolean create_new
)
1146 g_ptr_array_add (data
->signals
, g_new0 (GDBusSignalInfo
, 1));
1147 return data
->signals
->pdata
[data
->signals
->len
- 1];
1150 static GDBusPropertyInfo
*
1151 parse_data_get_property (ParseData
*data
,
1152 gboolean create_new
)
1155 g_ptr_array_add (data
->properties
, g_new0 (GDBusPropertyInfo
, 1));
1156 return data
->properties
->pdata
[data
->properties
->len
- 1];
1159 static GDBusInterfaceInfo
*
1160 parse_data_get_interface (ParseData
*data
,
1161 gboolean create_new
)
1164 g_ptr_array_add (data
->interfaces
, g_new0 (GDBusInterfaceInfo
, 1));
1165 return data
->interfaces
->pdata
[data
->interfaces
->len
- 1];
1168 static GDBusNodeInfo
*
1169 parse_data_get_node (ParseData
*data
,
1170 gboolean create_new
)
1173 g_ptr_array_add (data
->nodes
, g_new0 (GDBusNodeInfo
, 1));
1174 return data
->nodes
->pdata
[data
->nodes
->len
- 1];
1177 /* ---------------------------------------------------------------------------------------------------- */
1180 parse_data_new (void)
1184 data
= g_new0 (ParseData
, 1);
1186 /* initialize arrays */
1187 parse_data_steal_annotations (data
, NULL
);
1188 parse_data_steal_args (data
, NULL
);
1189 parse_data_steal_out_args (data
, NULL
);
1190 parse_data_steal_methods (data
, NULL
);
1191 parse_data_steal_signals (data
, NULL
);
1192 parse_data_steal_properties (data
, NULL
);
1193 parse_data_steal_interfaces (data
, NULL
);
1194 parse_data_steal_nodes (data
, NULL
);
1200 parse_data_free (ParseData
*data
)
1204 /* free stack of annotation arrays */
1205 for (l
= data
->annotations_stack
; l
!= NULL
; l
= l
->next
)
1207 GPtrArray
*annotations
= l
->data
;
1208 g_ptr_array_foreach (annotations
, (GFunc
) g_dbus_annotation_info_unref
, NULL
);
1209 g_ptr_array_free (annotations
, TRUE
);
1211 g_slist_free (data
->annotations_stack
);
1213 /* free stack of interface arrays */
1214 for (l
= data
->interfaces_stack
; l
!= NULL
; l
= l
->next
)
1216 GPtrArray
*interfaces
= l
->data
;
1217 g_ptr_array_foreach (interfaces
, (GFunc
) g_dbus_interface_info_unref
, NULL
);
1218 g_ptr_array_free (interfaces
, TRUE
);
1220 g_slist_free (data
->interfaces_stack
);
1222 /* free stack of node arrays */
1223 for (l
= data
->nodes_stack
; l
!= NULL
; l
= l
->next
)
1225 GPtrArray
*nodes
= l
->data
;
1226 g_ptr_array_foreach (nodes
, (GFunc
) g_dbus_node_info_unref
, NULL
);
1227 g_ptr_array_free (nodes
, TRUE
);
1229 g_slist_free (data
->nodes_stack
);
1231 /* free arrays (data->annotations, data->interfaces and data->nodes have been freed above) */
1232 parse_data_free_args (data
);
1233 parse_data_free_out_args (data
);
1234 parse_data_free_methods (data
);
1235 parse_data_free_signals (data
);
1236 parse_data_free_properties (data
);
1237 parse_data_free_interfaces (data
);
1238 parse_data_free_annotations (data
);
1239 parse_data_free_nodes (data
);
1244 /* ---------------------------------------------------------------------------------------------------- */
1247 parser_start_element (GMarkupParseContext
*context
,
1248 const gchar
*element_name
,
1249 const gchar
**attribute_names
,
1250 const gchar
**attribute_values
,
1254 ParseData
*data
= user_data
;
1258 const gchar
*access
;
1259 const gchar
*direction
;
1268 stack
= (GSList
*) g_markup_parse_context_get_element_stack (context
);
1270 /* ---------------------------------------------------------------------------------------------------- */
1271 if (strcmp (element_name
, "node") == 0)
1273 if (!(g_slist_length (stack
) >= 1 || strcmp (stack
->next
->data
, "node") != 0))
1275 g_set_error_literal (error
,
1277 G_MARKUP_ERROR_INVALID_CONTENT
,
1278 "<node> elements can only be top-level or embedded in other <node> elements");
1282 if (!g_markup_collect_attributes (element_name
,
1286 G_MARKUP_COLLECT_STRING
| G_MARKUP_COLLECT_OPTIONAL
, "name", &name
,
1287 /* some hand-written introspection XML documents use this */
1288 G_MARKUP_COLLECT_STRING
| G_MARKUP_COLLECT_OPTIONAL
, "xmlns:doc", NULL
,
1289 G_MARKUP_COLLECT_INVALID
))
1292 g_dbus_node_info_set (data
,
1293 parse_data_get_node (data
, TRUE
),
1299 /* push the currently retrieved interfaces and nodes on the stack and prepare new arrays */
1300 data
->interfaces_stack
= g_slist_prepend (data
->interfaces_stack
, data
->interfaces
);
1301 data
->interfaces
= NULL
;
1302 parse_data_steal_interfaces (data
, NULL
);
1304 data
->nodes_stack
= g_slist_prepend (data
->nodes_stack
, data
->nodes
);
1306 parse_data_steal_nodes (data
, NULL
);
1309 /* ---------------------------------------------------------------------------------------------------- */
1310 else if (strcmp (element_name
, "interface") == 0)
1312 if (g_slist_length (stack
) < 2 || strcmp (stack
->next
->data
, "node") != 0)
1314 g_set_error_literal (error
,
1316 G_MARKUP_ERROR_INVALID_CONTENT
,
1317 "<interface> elements can only be embedded in <node> elements");
1321 if (!g_markup_collect_attributes (element_name
,
1325 G_MARKUP_COLLECT_STRING
, "name", &name
,
1326 /* seen in the wild */
1327 G_MARKUP_COLLECT_STRING
| G_MARKUP_COLLECT_OPTIONAL
, "version", NULL
,
1328 G_MARKUP_COLLECT_INVALID
))
1331 g_dbus_interface_info_set (data
,
1332 parse_data_get_interface (data
, TRUE
),
1340 /* ---------------------------------------------------------------------------------------------------- */
1341 else if (strcmp (element_name
, "method") == 0)
1343 if (g_slist_length (stack
) < 2 || strcmp (stack
->next
->data
, "interface") != 0)
1345 g_set_error_literal (error
,
1347 G_MARKUP_ERROR_INVALID_CONTENT
,
1348 "<method> elements can only be embedded in <interface> elements");
1352 if (!g_markup_collect_attributes (element_name
,
1356 G_MARKUP_COLLECT_STRING
, "name", &name
,
1357 /* seen in the wild */
1358 G_MARKUP_COLLECT_STRING
| G_MARKUP_COLLECT_OPTIONAL
, "version", NULL
,
1359 G_MARKUP_COLLECT_INVALID
))
1362 g_dbus_method_info_set (data
,
1363 parse_data_get_method (data
, TRUE
),
1372 /* ---------------------------------------------------------------------------------------------------- */
1373 else if (strcmp (element_name
, "signal") == 0)
1375 if (g_slist_length (stack
) < 2 || strcmp (stack
->next
->data
, "interface") != 0)
1377 g_set_error_literal (error
,
1379 G_MARKUP_ERROR_INVALID_CONTENT
,
1380 "<signal> elements can only be embedded in <interface> elements");
1384 if (!g_markup_collect_attributes (element_name
,
1388 G_MARKUP_COLLECT_STRING
, "name", &name
,
1389 G_MARKUP_COLLECT_INVALID
))
1392 g_dbus_signal_info_set (data
,
1393 parse_data_get_signal (data
, TRUE
),
1401 /* ---------------------------------------------------------------------------------------------------- */
1402 else if (strcmp (element_name
, "property") == 0)
1404 GDBusPropertyInfoFlags flags
;
1406 if (g_slist_length (stack
) < 2 || strcmp (stack
->next
->data
, "interface") != 0)
1408 g_set_error_literal (error
,
1410 G_MARKUP_ERROR_INVALID_CONTENT
,
1411 "<property> elements can only be embedded in <interface> elements");
1415 if (!g_markup_collect_attributes (element_name
,
1419 G_MARKUP_COLLECT_STRING
, "name", &name
,
1420 G_MARKUP_COLLECT_STRING
, "type", &type
,
1421 G_MARKUP_COLLECT_STRING
, "access", &access
,
1422 G_MARKUP_COLLECT_INVALID
))
1425 if (strcmp (access
, "read") == 0)
1426 flags
= G_DBUS_PROPERTY_INFO_FLAGS_READABLE
;
1427 else if (strcmp (access
, "write") == 0)
1428 flags
= G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE
;
1429 else if (strcmp (access
, "readwrite") == 0)
1430 flags
= G_DBUS_PROPERTY_INFO_FLAGS_READABLE
| G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE
;
1435 G_MARKUP_ERROR_INVALID_CONTENT
,
1436 "Unknown value '%s' of access attribute for element <property>",
1441 g_dbus_property_info_set (data
,
1442 parse_data_get_property (data
, TRUE
),
1449 /* ---------------------------------------------------------------------------------------------------- */
1450 else if (strcmp (element_name
, "arg") == 0)
1455 if (g_slist_length (stack
) < 2 ||
1456 (strcmp (stack
->next
->data
, "method") != 0 &&
1457 strcmp (stack
->next
->data
, "signal") != 0))
1459 g_set_error_literal (error
,
1461 G_MARKUP_ERROR_INVALID_CONTENT
,
1462 "<arg> elements can only be embedded in <method> or <signal> elements");
1466 if (!g_markup_collect_attributes (element_name
,
1470 G_MARKUP_COLLECT_STRING
| G_MARKUP_COLLECT_OPTIONAL
, "name", &name
,
1471 G_MARKUP_COLLECT_STRING
| G_MARKUP_COLLECT_OPTIONAL
, "direction", &direction
,
1472 G_MARKUP_COLLECT_STRING
, "type", &type
,
1473 G_MARKUP_COLLECT_INVALID
))
1476 if (strcmp (stack
->next
->data
, "method") == 0)
1480 if (direction
!= NULL
)
1482 if (strcmp (direction
, "in") == 0)
1484 else if (strcmp (direction
, "out") == 0)
1490 G_MARKUP_ERROR_INVALID_CONTENT
,
1491 "Unknown value '%s' of direction attribute",
1497 if (is_in
&& strcmp (stack
->next
->data
, "signal") == 0)
1499 g_set_error_literal (error
,
1501 G_MARKUP_ERROR_INVALID_CONTENT
,
1502 "Only direction 'out' is allowed for <arg> elements embedded in <signal>");
1507 name_to_use
= g_strdup_printf ("arg_%d", data
->num_args
);
1509 name_to_use
= g_strdup (name
);
1514 g_dbus_arg_info_set (data
,
1515 parse_data_get_arg (data
, TRUE
),
1519 data
->last_arg_was_in
= TRUE
;
1523 g_dbus_arg_info_set (data
,
1524 parse_data_get_out_arg (data
, TRUE
),
1528 data
->last_arg_was_in
= FALSE
;
1532 g_free (name_to_use
);
1534 /* ---------------------------------------------------------------------------------------------------- */
1535 else if (strcmp (element_name
, "annotation") == 0)
1537 if (g_slist_length (stack
) < 2 ||
1538 (strcmp (stack
->next
->data
, "node") != 0 &&
1539 strcmp (stack
->next
->data
, "interface") != 0 &&
1540 strcmp (stack
->next
->data
, "signal") != 0 &&
1541 strcmp (stack
->next
->data
, "method") != 0 &&
1542 strcmp (stack
->next
->data
, "property") != 0 &&
1543 strcmp (stack
->next
->data
, "arg") != 0 &&
1544 strcmp (stack
->next
->data
, "annotation") != 0))
1546 g_set_error_literal (error
,
1548 G_MARKUP_ERROR_INVALID_CONTENT
,
1549 "<annotation> elements can only be embedded in <node>, <interface>, <signal>, <method>, <property>, <arg> or <annotation> elements");
1553 if (!g_markup_collect_attributes (element_name
,
1557 G_MARKUP_COLLECT_STRING
, "name", &name
,
1558 G_MARKUP_COLLECT_STRING
, "value", &value
,
1559 G_MARKUP_COLLECT_INVALID
))
1562 g_dbus_annotation_info_set (data
,
1563 parse_data_get_annotation (data
, TRUE
),
1568 /* ---------------------------------------------------------------------------------------------------- */
1571 /* don't bail on unknown elements; just ignore them */
1573 /* ---------------------------------------------------------------------------------------------------- */
1575 /* push the currently retrieved annotations on the stack and prepare a new one */
1576 data
->annotations_stack
= g_slist_prepend (data
->annotations_stack
, data
->annotations
);
1577 data
->annotations
= NULL
;
1578 parse_data_steal_annotations (data
, NULL
);
1584 /* ---------------------------------------------------------------------------------------------------- */
1586 static GDBusAnnotationInfo
**
1587 steal_annotations (ParseData
*data
)
1589 return parse_data_steal_annotations (data
, NULL
);
1594 parser_end_element (GMarkupParseContext
*context
,
1595 const gchar
*element_name
,
1599 ParseData
*data
= user_data
;
1600 gboolean have_popped_annotations
;
1602 have_popped_annotations
= FALSE
;
1604 if (strcmp (element_name
, "node") == 0)
1607 guint num_interfaces
;
1608 GDBusNodeInfo
**nodes
;
1609 GDBusInterfaceInfo
**interfaces
;
1611 nodes
= parse_data_steal_nodes (data
, &num_nodes
);
1612 interfaces
= parse_data_steal_interfaces (data
, &num_interfaces
);
1614 /* destroy the nodes, interfaces for scope we're exiting and and pop the nodes, interfaces from the
1615 * scope we're reentering
1617 parse_data_free_interfaces (data
);
1618 data
->interfaces
= (GPtrArray
*) data
->interfaces_stack
->data
;
1619 data
->interfaces_stack
= g_slist_remove (data
->interfaces_stack
, data
->interfaces_stack
->data
);
1621 parse_data_free_nodes (data
);
1622 data
->nodes
= (GPtrArray
*) data
->nodes_stack
->data
;
1623 data
->nodes_stack
= g_slist_remove (data
->nodes_stack
, data
->nodes_stack
->data
);
1625 g_dbus_node_info_set (data
,
1626 parse_data_get_node (data
, FALSE
),
1630 steal_annotations (data
));
1633 else if (strcmp (element_name
, "interface") == 0)
1637 guint num_properties
;
1638 GDBusMethodInfo
**methods
;
1639 GDBusSignalInfo
**signals
;
1640 GDBusPropertyInfo
**properties
;
1642 methods
= parse_data_steal_methods (data
, &num_methods
);
1643 signals
= parse_data_steal_signals (data
, &num_signals
);
1644 properties
= parse_data_steal_properties (data
, &num_properties
);
1646 g_dbus_interface_info_set (data
,
1647 parse_data_get_interface (data
, FALSE
),
1652 steal_annotations (data
));
1655 else if (strcmp (element_name
, "method") == 0)
1659 GDBusArgInfo
**in_args
;
1660 GDBusArgInfo
**out_args
;
1662 in_args
= parse_data_steal_args (data
, &in_num_args
);
1663 out_args
= parse_data_steal_out_args (data
, &out_num_args
);
1665 g_dbus_method_info_set (data
,
1666 parse_data_get_method (data
, FALSE
),
1670 steal_annotations (data
));
1672 else if (strcmp (element_name
, "signal") == 0)
1675 GDBusArgInfo
**args
;
1677 args
= parse_data_steal_out_args (data
, &num_args
);
1679 g_dbus_signal_info_set (data
,
1680 parse_data_get_signal (data
, FALSE
),
1683 steal_annotations (data
));
1685 else if (strcmp (element_name
, "property") == 0)
1687 g_dbus_property_info_set (data
,
1688 parse_data_get_property (data
, FALSE
),
1691 G_DBUS_PROPERTY_INFO_FLAGS_NONE
,
1692 steal_annotations (data
));
1694 else if (strcmp (element_name
, "arg") == 0)
1696 g_dbus_arg_info_set (data
,
1697 data
->last_arg_was_in
? parse_data_get_arg (data
, FALSE
) : parse_data_get_out_arg (data
, FALSE
),
1700 steal_annotations (data
));
1702 else if (strcmp (element_name
, "annotation") == 0)
1704 GDBusAnnotationInfo
**embedded_annotations
;
1706 embedded_annotations
= steal_annotations (data
);
1708 /* destroy the annotations for scope we're exiting and and pop the annotations from the scope we're reentering */
1709 parse_data_free_annotations (data
);
1710 data
->annotations
= (GPtrArray
*) data
->annotations_stack
->data
;
1711 data
->annotations_stack
= g_slist_remove (data
->annotations_stack
, data
->annotations_stack
->data
);
1713 have_popped_annotations
= TRUE
;
1715 g_dbus_annotation_info_set (data
,
1716 parse_data_get_annotation (data
, FALSE
),
1719 embedded_annotations
);
1723 /* don't bail on unknown elements; just ignore them */
1726 if (!have_popped_annotations
)
1728 /* destroy the annotations for scope we're exiting and and pop the annotations from the scope we're reentering */
1729 parse_data_free_annotations (data
);
1730 data
->annotations
= (GPtrArray
*) data
->annotations_stack
->data
;
1731 data
->annotations_stack
= g_slist_remove (data
->annotations_stack
, data
->annotations_stack
->data
);
1735 /* ---------------------------------------------------------------------------------------------------- */
1738 parser_error (GMarkupParseContext
*context
,
1745 g_markup_parse_context_get_position (context
, &line_number
, &char_number
);
1747 g_prefix_error (&error
, "%d:%d: ",
1752 /* ---------------------------------------------------------------------------------------------------- */
1755 * g_dbus_node_info_new_for_xml:
1756 * @xml_data: Valid D-Bus introspection XML.
1757 * @error: Return location for error.
1759 * Parses @xml_data and returns a #GDBusNodeInfo representing the data.
1761 * The introspection XML must contain exactly one top-level
1764 * Note that this routine is using a
1765 * [GMarkup][glib-Simple-XML-Subset-Parser.description]-based
1766 * parser that only accepts a subset of valid XML documents.
1768 * Returns: A #GDBusNodeInfo structure or %NULL if @error is set. Free
1769 * with g_dbus_node_info_unref().
1774 g_dbus_node_info_new_for_xml (const gchar
*xml_data
,
1778 GMarkupParseContext
*context
;
1779 GMarkupParser
*parser
;
1782 GDBusNodeInfo
**ughret
;
1788 parser
= g_new0 (GMarkupParser
, 1);
1789 parser
->start_element
= parser_start_element
;
1790 parser
->end_element
= parser_end_element
;
1791 parser
->error
= parser_error
;
1793 data
= parse_data_new ();
1794 context
= g_markup_parse_context_new (parser
,
1795 G_MARKUP_IGNORE_QUALIFIED
,
1797 (GDestroyNotify
) parse_data_free
);
1799 if (!g_markup_parse_context_parse (context
,
1805 if (!g_markup_parse_context_end_parse (context
, error
))
1808 ughret
= parse_data_steal_nodes (data
, &num_nodes
);
1816 G_MARKUP_ERROR_INVALID_CONTENT
,
1817 "Expected a single node in introspection XML, found %d",
1821 for (n
= 0; n
< num_nodes
; n
++)
1823 g_dbus_node_info_unref (ughret
[n
]);
1833 if (context
!= NULL
)
1834 g_markup_parse_context_free (context
);
1839 /* ---------------------------------------------------------------------------------------------------- */
1842 * g_dbus_annotation_info_lookup:
1843 * @annotations: (array zero-terminated=1) (nullable): A %NULL-terminated array of annotations or %NULL.
1844 * @name: The name of the annotation to look up.
1846 * Looks up the value of an annotation.
1848 * The cost of this function is O(n) in number of annotations.
1850 * Returns: The value or %NULL if not found. Do not free, it is owned by @annotations.
1855 g_dbus_annotation_info_lookup (GDBusAnnotationInfo
**annotations
,
1862 for (n
= 0; annotations
!= NULL
&& annotations
[n
] != NULL
; n
++)
1864 if (g_strcmp0 (annotations
[n
]->key
, name
) == 0)
1866 ret
= annotations
[n
]->value
;
1875 /* ---------------------------------------------------------------------------------------------------- */
1877 G_LOCK_DEFINE_STATIC (info_cache_lock
);
1883 /* gchar* -> GDBusMethodInfo* */
1884 GHashTable
*method_name_to_data
;
1886 /* gchar* -> GDBusMethodInfo* */
1887 GHashTable
*signal_name_to_data
;
1889 /* gchar* -> GDBusMethodInfo* */
1890 GHashTable
*property_name_to_data
;
1894 info_cache_free (InfoCacheEntry
*cache
)
1896 g_assert (cache
->use_count
== 0);
1897 g_hash_table_unref (cache
->method_name_to_data
);
1898 g_hash_table_unref (cache
->signal_name_to_data
);
1899 g_hash_table_unref (cache
->property_name_to_data
);
1900 g_slice_free (InfoCacheEntry
, cache
);
1903 /* maps from GDBusInterfaceInfo* to InfoCacheEntry* */
1904 static GHashTable
*info_cache
= NULL
;
1906 /* ---------------------------------------------------------------------------------------------------- */
1909 * g_dbus_interface_info_lookup_method:
1910 * @info: A #GDBusInterfaceInfo.
1911 * @name: A D-Bus method name (typically in CamelCase)
1913 * Looks up information about a method.
1915 * The cost of this function is O(n) in number of methods unless
1916 * g_dbus_interface_info_cache_build() has been used on @info.
1918 * Returns: (transfer none): A #GDBusMethodInfo or %NULL if not found. Do not free, it is owned by @info.
1923 g_dbus_interface_info_lookup_method (GDBusInterfaceInfo
*info
,
1927 GDBusMethodInfo
*result
;
1929 G_LOCK (info_cache_lock
);
1930 if (G_LIKELY (info_cache
!= NULL
))
1932 InfoCacheEntry
*cache
;
1933 cache
= g_hash_table_lookup (info_cache
, info
);
1934 if (G_LIKELY (cache
!= NULL
))
1936 result
= g_hash_table_lookup (cache
->method_name_to_data
, name
);
1937 G_UNLOCK (info_cache_lock
);
1941 G_UNLOCK (info_cache_lock
);
1943 for (n
= 0; info
->methods
!= NULL
&& info
->methods
[n
] != NULL
; n
++)
1945 GDBusMethodInfo
*i
= info
->methods
[n
];
1947 if (g_strcmp0 (i
->name
, name
) == 0)
1960 /* ---------------------------------------------------------------------------------------------------- */
1963 * g_dbus_interface_info_lookup_signal:
1964 * @info: A #GDBusInterfaceInfo.
1965 * @name: A D-Bus signal name (typically in CamelCase)
1967 * Looks up information about a signal.
1969 * The cost of this function is O(n) in number of signals unless
1970 * g_dbus_interface_info_cache_build() has been used on @info.
1972 * Returns: (transfer none): A #GDBusSignalInfo or %NULL if not found. Do not free, it is owned by @info.
1977 g_dbus_interface_info_lookup_signal (GDBusInterfaceInfo
*info
,
1981 GDBusSignalInfo
*result
;
1983 G_LOCK (info_cache_lock
);
1984 if (G_LIKELY (info_cache
!= NULL
))
1986 InfoCacheEntry
*cache
;
1987 cache
= g_hash_table_lookup (info_cache
, info
);
1988 if (G_LIKELY (cache
!= NULL
))
1990 result
= g_hash_table_lookup (cache
->signal_name_to_data
, name
);
1991 G_UNLOCK (info_cache_lock
);
1995 G_UNLOCK (info_cache_lock
);
1997 for (n
= 0; info
->signals
!= NULL
&& info
->signals
[n
] != NULL
; n
++)
1999 GDBusSignalInfo
*i
= info
->signals
[n
];
2001 if (g_strcmp0 (i
->name
, name
) == 0)
2014 /* ---------------------------------------------------------------------------------------------------- */
2017 * g_dbus_interface_info_lookup_property:
2018 * @info: A #GDBusInterfaceInfo.
2019 * @name: A D-Bus property name (typically in CamelCase).
2021 * Looks up information about a property.
2023 * The cost of this function is O(n) in number of properties unless
2024 * g_dbus_interface_info_cache_build() has been used on @info.
2026 * Returns: (transfer none): A #GDBusPropertyInfo or %NULL if not found. Do not free, it is owned by @info.
2031 g_dbus_interface_info_lookup_property (GDBusInterfaceInfo
*info
,
2035 GDBusPropertyInfo
*result
;
2037 G_LOCK (info_cache_lock
);
2038 if (G_LIKELY (info_cache
!= NULL
))
2040 InfoCacheEntry
*cache
;
2041 cache
= g_hash_table_lookup (info_cache
, info
);
2042 if (G_LIKELY (cache
!= NULL
))
2044 result
= g_hash_table_lookup (cache
->property_name_to_data
, name
);
2045 G_UNLOCK (info_cache_lock
);
2049 G_UNLOCK (info_cache_lock
);
2051 for (n
= 0; info
->properties
!= NULL
&& info
->properties
[n
] != NULL
; n
++)
2053 GDBusPropertyInfo
*i
= info
->properties
[n
];
2055 if (g_strcmp0 (i
->name
, name
) == 0)
2068 /* ---------------------------------------------------------------------------------------------------- */
2071 * g_dbus_interface_info_cache_build:
2072 * @info: A #GDBusInterfaceInfo.
2074 * Builds a lookup-cache to speed up
2075 * g_dbus_interface_info_lookup_method(),
2076 * g_dbus_interface_info_lookup_signal() and
2077 * g_dbus_interface_info_lookup_property().
2079 * If this has already been called with @info, the existing cache is
2080 * used and its use count is increased.
2082 * Note that @info cannot be modified until
2083 * g_dbus_interface_info_cache_release() is called.
2088 g_dbus_interface_info_cache_build (GDBusInterfaceInfo
*info
)
2090 InfoCacheEntry
*cache
;
2093 G_LOCK (info_cache_lock
);
2094 if (info_cache
== NULL
)
2095 info_cache
= g_hash_table_new_full (g_direct_hash
, g_direct_equal
, NULL
, (GDestroyNotify
) info_cache_free
);
2096 cache
= g_hash_table_lookup (info_cache
, info
);
2099 cache
->use_count
+= 1;
2102 cache
= g_slice_new0 (InfoCacheEntry
);
2103 cache
->use_count
= 1;
2104 cache
->method_name_to_data
= g_hash_table_new (g_str_hash
, g_str_equal
);
2105 cache
->signal_name_to_data
= g_hash_table_new (g_str_hash
, g_str_equal
);
2106 cache
->property_name_to_data
= g_hash_table_new (g_str_hash
, g_str_equal
);
2107 for (n
= 0; info
->methods
!= NULL
&& info
->methods
[n
] != NULL
; n
++)
2108 g_hash_table_insert (cache
->method_name_to_data
, info
->methods
[n
]->name
, info
->methods
[n
]);
2109 for (n
= 0; info
->signals
!= NULL
&& info
->signals
[n
] != NULL
; n
++)
2110 g_hash_table_insert (cache
->signal_name_to_data
, info
->signals
[n
]->name
, info
->signals
[n
]);
2111 for (n
= 0; info
->properties
!= NULL
&& info
->properties
[n
] != NULL
; n
++)
2112 g_hash_table_insert (cache
->property_name_to_data
, info
->properties
[n
]->name
, info
->properties
[n
]);
2113 g_hash_table_insert (info_cache
, info
, cache
);
2115 G_UNLOCK (info_cache_lock
);
2119 * g_dbus_interface_info_cache_release:
2120 * @info: A GDBusInterfaceInfo
2122 * Decrements the usage count for the cache for @info built by
2123 * g_dbus_interface_info_cache_build() (if any) and frees the
2124 * resources used by the cache if the usage count drops to zero.
2129 g_dbus_interface_info_cache_release (GDBusInterfaceInfo
*info
)
2131 InfoCacheEntry
*cache
;
2133 G_LOCK (info_cache_lock
);
2134 if (G_UNLIKELY (info_cache
== NULL
))
2136 g_warning ("%s called for interface %s but there is no cache", info
->name
, G_STRFUNC
);
2140 cache
= g_hash_table_lookup (info_cache
, info
);
2141 if (G_UNLIKELY (cache
== NULL
))
2143 g_warning ("%s called for interface %s but there is no cache entry", info
->name
, G_STRFUNC
);
2146 cache
->use_count
-= 1;
2147 if (cache
->use_count
== 0)
2149 g_hash_table_remove (info_cache
, info
);
2150 /* could nuke info_cache itself if empty */
2153 G_UNLOCK (info_cache_lock
);
2157 /* ---------------------------------------------------------------------------------------------------- */
2160 * g_dbus_node_info_lookup_interface:
2161 * @info: A #GDBusNodeInfo.
2162 * @name: A D-Bus interface name.
2164 * Looks up information about an interface.
2166 * The cost of this function is O(n) in number of interfaces.
2168 * Returns: (transfer none): A #GDBusInterfaceInfo or %NULL if not found. Do not free, it is owned by @info.
2172 GDBusInterfaceInfo
*
2173 g_dbus_node_info_lookup_interface (GDBusNodeInfo
*info
,
2177 GDBusInterfaceInfo
*result
;
2179 for (n
= 0; info
->interfaces
!= NULL
&& info
->interfaces
[n
] != NULL
; n
++)
2181 GDBusInterfaceInfo
*i
= info
->interfaces
[n
];
2183 if (g_strcmp0 (i
->name
, name
) == 0)