Fix memory leaks in the gdbus introspection parser
[platform/upstream/glib.git] / gio / gdbusintrospection.c
1 /* GDBus - GLib D-Bus Library
2  *
3  * Copyright (C) 2008-2010 Red Hat, Inc.
4  *
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 of the License, or (at your option) any later version.
9  *
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.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18  * Boston, MA 02111-1307, USA.
19  *
20  * Author: David Zeuthen <davidz@redhat.com>
21  */
22
23 #include "config.h"
24
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include "gdbusintrospection.h"
29
30 #include "glibintl.h"
31
32 /**
33  * SECTION:gdbusintrospection
34  * @title: D-Bus Introspection Data
35  * @short_description: Node and interface description data structures
36  * @include: gio/gio.h
37  *
38  * Various data structures and convenience routines to parse and
39  * generate D-Bus introspection XML. Introspection information is
40  * used when registering objects with g_dbus_connection_register_object().
41  *
42  * The format of D-Bus introspection XML is specified in the
43  * <link linkend="http://dbus.freedesktop.org/doc/dbus-specification.html&num;introspection-format">D-Bus specification</link>.
44  */
45
46 /* ---------------------------------------------------------------------------------------------------- */
47
48 #define _MY_DEFINE_BOXED_TYPE(TypeName, type_name) \
49   G_DEFINE_BOXED_TYPE (TypeName, type_name, type_name##_ref, type_name##_unref)
50
51 _MY_DEFINE_BOXED_TYPE (GDBusNodeInfo,       g_dbus_node_info);
52 _MY_DEFINE_BOXED_TYPE (GDBusInterfaceInfo,  g_dbus_interface_info);
53 _MY_DEFINE_BOXED_TYPE (GDBusMethodInfo,     g_dbus_method_info);
54 _MY_DEFINE_BOXED_TYPE (GDBusSignalInfo,     g_dbus_signal_info);
55 _MY_DEFINE_BOXED_TYPE (GDBusPropertyInfo,   g_dbus_property_info);
56 _MY_DEFINE_BOXED_TYPE (GDBusArgInfo,        g_dbus_arg_info);
57 _MY_DEFINE_BOXED_TYPE (GDBusAnnotationInfo, g_dbus_annotation_info);
58
59 /* ---------------------------------------------------------------------------------------------------- */
60
61 typedef struct
62 {
63   /* stuff we are currently collecting */
64   GPtrArray *args;
65   GPtrArray *out_args;
66   GPtrArray *methods;
67   GPtrArray *signals;
68   GPtrArray *properties;
69   GPtrArray *interfaces;
70   GPtrArray *nodes;
71   GPtrArray *annotations;
72
73   /* A list of GPtrArray's containing annotations */
74   GSList *annotations_stack;
75
76   /* A list of GPtrArray's containing interfaces */
77   GSList *interfaces_stack;
78
79   /* A list of GPtrArray's containing nodes */
80   GSList *nodes_stack;
81
82   /* Whether the direction was "in" for last parsed arg */
83   gboolean last_arg_was_in;
84
85   /* Number of args currently being collected; used for assigning
86    * names to args without a "name" attribute
87    */
88   guint num_args;
89
90 } ParseData;
91
92 /* ---------------------------------------------------------------------------------------------------- */
93
94 /**
95  * g_dbus_node_info_ref:
96  * @info: A #GDBusNodeInfo
97  *
98  * If @info is statically allocated does nothing. Otherwise increases
99  * the reference count.
100  *
101  * Returns: The same @info.
102  *
103  * Since: 2.26
104  */
105 GDBusNodeInfo *
106 g_dbus_node_info_ref (GDBusNodeInfo *info)
107 {
108   if (info->ref_count == -1)
109     return info;
110   g_atomic_int_inc (&info->ref_count);
111   return info;
112 }
113
114 /**
115  * g_dbus_interface_info_ref:
116  * @info: A #GDBusInterfaceInfo
117  *
118  * If @info is statically allocated does nothing. Otherwise increases
119  * the reference count.
120  *
121  * Returns: The same @info.
122  *
123  * Since: 2.26
124  */
125 GDBusInterfaceInfo *
126 g_dbus_interface_info_ref (GDBusInterfaceInfo *info)
127 {
128   if (info->ref_count == -1)
129     return info;
130   g_atomic_int_inc (&info->ref_count);
131   return info;
132 }
133
134 /**
135  * g_dbus_method_info_ref:
136  * @info: A #GDBusMethodInfo
137  *
138  * If @info is statically allocated does nothing. Otherwise increases
139  * the reference count.
140  *
141  * Returns: The same @info.
142  *
143  * Since: 2.26
144  */
145 GDBusMethodInfo *
146 g_dbus_method_info_ref (GDBusMethodInfo *info)
147 {
148   if (info->ref_count == -1)
149     return info;
150   g_atomic_int_inc (&info->ref_count);
151   return info;
152 }
153
154 /**
155  * g_dbus_signal_info_ref:
156  * @info: A #GDBusSignalInfo
157  *
158  * If @info is statically allocated does nothing. Otherwise increases
159  * the reference count.
160  *
161  * Returns: The same @info.
162  *
163  * Since: 2.26
164  */
165 GDBusSignalInfo *
166 g_dbus_signal_info_ref (GDBusSignalInfo *info)
167 {
168   if (info->ref_count == -1)
169     return info;
170   g_atomic_int_inc (&info->ref_count);
171   return info;
172 }
173
174 /**
175  * g_dbus_property_info_ref:
176  * @info: A #GDBusPropertyInfo
177  *
178  * If @info is statically allocated does nothing. Otherwise increases
179  * the reference count.
180  *
181  * Returns: The same @info.
182  *
183  * Since: 2.26
184  */
185 GDBusPropertyInfo *
186 g_dbus_property_info_ref (GDBusPropertyInfo *info)
187 {
188   if (info->ref_count == -1)
189     return info;
190   g_atomic_int_inc (&info->ref_count);
191   return info;
192 }
193
194 /**
195  * g_dbus_arg_info_ref:
196  * @info: A #GDBusArgInfo
197  *
198  * If @info is statically allocated does nothing. Otherwise increases
199  * the reference count.
200  *
201  * Returns: The same @info.
202  *
203  * Since: 2.26
204  */
205 GDBusArgInfo *
206 g_dbus_arg_info_ref (GDBusArgInfo *info)
207 {
208   if (info->ref_count == -1)
209     return info;
210   g_atomic_int_inc (&info->ref_count);
211   return info;
212 }
213
214 /**
215  * g_dbus_annotation_info_ref:
216  * @info: A #GDBusNodeInfo
217  *
218  * If @info is statically allocated does nothing. Otherwise increases
219  * the reference count.
220  *
221  * Returns: The same @info.
222  *
223  * Since: 2.26
224  */
225 GDBusAnnotationInfo *
226 g_dbus_annotation_info_ref (GDBusAnnotationInfo *info)
227 {
228   if (info->ref_count == -1)
229     return info;
230   g_atomic_int_inc (&info->ref_count);
231   return info;
232 }
233
234 /* ---------------------------------------------------------------------------------------------------- */
235
236 static void
237 free_null_terminated_array (gpointer array, GDestroyNotify unref_func)
238 {
239   guint n;
240   gpointer *p = array;
241   if (p == NULL)
242     return;
243   for (n = 0; p[n] != NULL; n++)
244     unref_func (p[n]);
245   g_free (p);
246 }
247
248 /**
249  * g_dbus_annotation_info_unref:
250  * @info: A #GDBusAnnotationInfo.
251  *
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.
255  *
256  * Since: 2.26
257  */
258 void
259 g_dbus_annotation_info_unref (GDBusAnnotationInfo *info)
260 {
261   if (info->ref_count == -1)
262     return;
263   if (g_atomic_int_dec_and_test (&info->ref_count))
264     {
265       g_free (info->key);
266       g_free (info->value);
267       free_null_terminated_array (info->annotations, (GDestroyNotify) g_dbus_annotation_info_unref);
268       g_free (info);
269     }
270 }
271
272 /**
273  * g_dbus_arg_info_unref:
274  * @info: A #GDBusArgInfo.
275  *
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.
279  *
280  * Since: 2.26
281  */
282 void
283 g_dbus_arg_info_unref (GDBusArgInfo *info)
284 {
285   if (info->ref_count == -1)
286     return;
287   if (g_atomic_int_dec_and_test (&info->ref_count))
288     {
289       g_free (info->name);
290       g_free (info->signature);
291       free_null_terminated_array (info->annotations, (GDestroyNotify) g_dbus_annotation_info_unref);
292       g_free (info);
293     }
294 }
295
296 /**
297  * g_dbus_method_info_unref:
298  * @info: A #GDBusMethodInfo.
299  *
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.
303  *
304  * Since: 2.26
305  */
306 void
307 g_dbus_method_info_unref (GDBusMethodInfo *info)
308 {
309   if (info->ref_count == -1)
310     return;
311   if (g_atomic_int_dec_and_test (&info->ref_count))
312     {
313       g_free (info->name);
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);
317       g_free (info);
318     }
319 }
320
321 /**
322  * g_dbus_signal_info_unref:
323  * @info: A #GDBusSignalInfo.
324  *
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.
328  *
329  * Since: 2.26
330  */
331 void
332 g_dbus_signal_info_unref (GDBusSignalInfo *info)
333 {
334   if (info->ref_count == -1)
335     return;
336   if (g_atomic_int_dec_and_test (&info->ref_count))
337     {
338       g_free (info->name);
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);
341       g_free (info);
342     }
343 }
344
345 /**
346  * g_dbus_property_info_unref:
347  * @info: A #GDBusPropertyInfo.
348  *
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.
352  *
353  * Since: 2.26
354  */
355 void
356 g_dbus_property_info_unref (GDBusPropertyInfo *info)
357 {
358   if (info->ref_count == -1)
359     return;
360   if (g_atomic_int_dec_and_test (&info->ref_count))
361     {
362       g_free (info->name);
363       g_free (info->signature);
364       free_null_terminated_array (info->annotations, (GDestroyNotify) g_dbus_annotation_info_unref);
365       g_free (info);
366     }
367 }
368
369 /**
370  * g_dbus_interface_info_unref:
371  * @info: A #GDBusInterfaceInfo.
372  *
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.
376  *
377  * Since: 2.26
378  */
379 void
380 g_dbus_interface_info_unref (GDBusInterfaceInfo *info)
381 {
382   if (info->ref_count == -1)
383     return;
384   if (g_atomic_int_dec_and_test (&info->ref_count))
385     {
386       g_free (info->name);
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);
391       g_free (info);
392     }
393 }
394
395 /**
396  * g_dbus_node_info_unref:
397  * @info: A #GDBusNodeInfo.
398  *
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.
402  *
403  * Since: 2.26
404  */
405 void
406 g_dbus_node_info_unref (GDBusNodeInfo *info)
407 {
408   if (info->ref_count == -1)
409     return;
410   if (g_atomic_int_dec_and_test (&info->ref_count))
411     {
412       g_free (info->path);
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);
416       g_free (info);
417     }
418 }
419
420 /* ---------------------------------------------------------------------------------------------------- */
421
422 static void
423 g_dbus_annotation_info_set (ParseData            *data,
424                             GDBusAnnotationInfo  *info,
425                             const gchar          *key,
426                             const gchar          *value,
427                             GDBusAnnotationInfo **embedded_annotations)
428 {
429   info->ref_count = 1;
430
431   if (key != NULL)
432     info->key = g_strdup (key);
433
434   if (value != NULL)
435     info->value = g_strdup (value);
436
437   if (embedded_annotations != NULL)
438     info->annotations = embedded_annotations;
439 }
440
441 static void
442 g_dbus_arg_info_set (ParseData            *data,
443                      GDBusArgInfo         *info,
444                      const gchar          *name,
445                      const gchar          *signature,
446                      GDBusAnnotationInfo **annotations)
447 {
448   info->ref_count = 1;
449
450   /* name may be NULL - TODO: compute name? */
451   if (name != NULL)
452     info->name = g_strdup (name);
453
454   if (signature != NULL)
455     info->signature = g_strdup (signature);
456
457   if (annotations != NULL)
458     info->annotations = annotations;
459 }
460
461 static void
462 g_dbus_method_info_set (ParseData            *data,
463                         GDBusMethodInfo      *info,
464                         const gchar          *name,
465                         GDBusArgInfo        **in_args,
466                         GDBusArgInfo        **out_args,
467                         GDBusAnnotationInfo **annotations)
468 {
469   info->ref_count = 1;
470
471   if (name != NULL)
472     info->name = g_strdup (name);
473
474   if (in_args != NULL)
475     info->in_args = in_args;
476
477   if (out_args != NULL)
478     info->out_args = out_args;
479
480   if (annotations != NULL)
481     info->annotations = annotations;
482 }
483
484 static void
485 g_dbus_signal_info_set (ParseData            *data,
486                         GDBusSignalInfo      *info,
487                         const gchar          *name,
488                         GDBusArgInfo        **args,
489                         GDBusAnnotationInfo **annotations)
490 {
491   info->ref_count = 1;
492
493   if (name != NULL)
494     info->name = g_strdup (name);
495
496   if (args != NULL)
497     info->args = args;
498
499   if (annotations != NULL)
500     info->annotations = annotations;
501 }
502
503 static void
504 g_dbus_property_info_set (ParseData               *data,
505                           GDBusPropertyInfo       *info,
506                           const gchar             *name,
507                           const gchar             *signature,
508                           GDBusPropertyInfoFlags   flags,
509                           GDBusAnnotationInfo    **annotations)
510 {
511   info->ref_count = 1;
512
513   if (name != NULL)
514     info->name = g_strdup (name);
515
516   if (flags != G_DBUS_PROPERTY_INFO_FLAGS_NONE)
517     info->flags = flags;
518
519   if (signature != NULL)
520     info->signature = g_strdup (signature);
521
522   if (annotations != NULL)
523     info->annotations = annotations;
524 }
525
526 static void
527 g_dbus_interface_info_set (ParseData            *data,
528                            GDBusInterfaceInfo   *info,
529                            const gchar          *name,
530                            GDBusMethodInfo     **methods,
531                            GDBusSignalInfo     **signals,
532                            GDBusPropertyInfo   **properties,
533                            GDBusAnnotationInfo **annotations)
534 {
535   info->ref_count = 1;
536
537   if (name != NULL)
538     info->name = g_strdup (name);
539
540   if (methods != NULL)
541     info->methods = methods;
542
543   if (signals != NULL)
544     info->signals = signals;
545
546   if (properties != NULL)
547     info->properties = properties;
548
549   if (annotations != NULL)
550     info->annotations = annotations;
551 }
552
553 static void
554 g_dbus_node_info_set (ParseData            *data,
555                       GDBusNodeInfo        *info,
556                       const gchar          *path,
557                       GDBusInterfaceInfo  **interfaces,
558                       GDBusNodeInfo       **nodes,
559                       GDBusAnnotationInfo **annotations)
560 {
561   info->ref_count = 1;
562
563   if (path != NULL)
564     {
565       info->path = g_strdup (path);
566       /* TODO: relative / absolute path snafu */
567     }
568
569   if (interfaces != NULL)
570     info->interfaces = interfaces;
571
572   if (nodes != NULL)
573     info->nodes = nodes;
574
575   if (annotations != NULL)
576     info->annotations = annotations;
577 }
578
579 /* ---------------------------------------------------------------------------------------------------- */
580
581 static void
582 g_dbus_annotation_info_generate_xml (GDBusAnnotationInfo *info,
583                                      guint                indent,
584                                      GString             *string_builder)
585 {
586   guint n;
587
588   g_string_append_printf (string_builder, "%*s<annotation name=\"%s\" value=\"%s\"",
589                           indent, "",
590                           info->key,
591                           info->value);
592
593   if (info->annotations == NULL)
594     {
595       g_string_append (string_builder, "/>\n");
596     }
597   else
598     {
599       g_string_append (string_builder, ">\n");
600
601       for (n = 0; info->annotations != NULL && info->annotations[n] != NULL; n++)
602         g_dbus_annotation_info_generate_xml (info->annotations[n],
603                                              indent + 2,
604                                              string_builder);
605
606       g_string_append_printf (string_builder, "%*s</annotation>\n",
607                               indent, "");
608     }
609
610 }
611
612 static void
613 g_dbus_arg_info_generate_xml (GDBusArgInfo *info,
614                               guint         indent,
615                               const gchar  *extra_attributes,
616                               GString      *string_builder)
617 {
618   guint n;
619
620   g_string_append_printf (string_builder, "%*s<arg type=\"%s\"",
621                           indent, "",
622                           info->signature);
623
624   if (info->name != NULL)
625     g_string_append_printf (string_builder, " name=\"%s\"", info->name);
626
627   if (extra_attributes != NULL)
628     g_string_append_printf (string_builder, " %s", extra_attributes);
629
630   if (info->annotations == NULL)
631     {
632       g_string_append (string_builder, "/>\n");
633     }
634   else
635     {
636       g_string_append (string_builder, ">\n");
637
638       for (n = 0; info->annotations != NULL && info->annotations[n] != NULL; n++)
639         g_dbus_annotation_info_generate_xml (info->annotations[n],
640                                              indent + 2,
641                                              string_builder);
642
643       g_string_append_printf (string_builder, "%*s</arg>\n", indent, "");
644     }
645
646 }
647
648 static void
649 g_dbus_method_info_generate_xml (GDBusMethodInfo *info,
650                                  guint            indent,
651                                  GString         *string_builder)
652 {
653   guint n;
654
655   g_string_append_printf (string_builder, "%*s<method name=\"%s\"",
656                           indent, "",
657                           info->name);
658
659   if (info->annotations == NULL && info->in_args == NULL && info->out_args == NULL)
660     {
661       g_string_append (string_builder, "/>\n");
662     }
663   else
664     {
665       g_string_append (string_builder, ">\n");
666
667       for (n = 0; info->annotations != NULL && info->annotations[n] != NULL; n++)
668         g_dbus_annotation_info_generate_xml (info->annotations[n],
669                                              indent + 2,
670                                              string_builder);
671
672       for (n = 0; info->in_args != NULL && info->in_args[n] != NULL; n++)
673         g_dbus_arg_info_generate_xml (info->in_args[n],
674                                       indent + 2,
675                                       "direction=\"in\"",
676                                       string_builder);
677
678       for (n = 0; info->out_args != NULL && info->out_args[n] != NULL; n++)
679         g_dbus_arg_info_generate_xml (info->out_args[n],
680                                       indent + 2,
681                                       "direction=\"out\"",
682                                       string_builder);
683
684       g_string_append_printf (string_builder, "%*s</method>\n", indent, "");
685     }
686 }
687
688 static void
689 g_dbus_signal_info_generate_xml (GDBusSignalInfo *info,
690                                  guint            indent,
691                                  GString         *string_builder)
692 {
693   guint n;
694
695   g_string_append_printf (string_builder, "%*s<signal name=\"%s\"",
696                           indent, "",
697                           info->name);
698
699   if (info->annotations == NULL && info->args == NULL)
700     {
701       g_string_append (string_builder, "/>\n");
702     }
703   else
704     {
705       g_string_append (string_builder, ">\n");
706
707       for (n = 0; info->annotations != NULL && info->annotations[n] != NULL; n++)
708         g_dbus_annotation_info_generate_xml (info->annotations[n],
709                                              indent + 2,
710                                              string_builder);
711
712       for (n = 0; info->args != NULL && info->args[n] != NULL; n++)
713         g_dbus_arg_info_generate_xml (info->args[n],
714                                       indent + 2,
715                                       NULL,
716                                       string_builder);
717
718       g_string_append_printf (string_builder, "%*s</signal>\n", indent, "");
719     }
720 }
721
722 static void
723 g_dbus_property_info_generate_xml (GDBusPropertyInfo *info,
724                                    guint              indent,
725                                    GString           *string_builder)
726 {
727   guint n;
728   const gchar *access_string;
729
730   if ((info->flags & G_DBUS_PROPERTY_INFO_FLAGS_READABLE) &&
731       (info->flags & G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE))
732     {
733       access_string = "readwrite";
734     }
735   else if (info->flags & G_DBUS_PROPERTY_INFO_FLAGS_READABLE)
736     {
737       access_string = "read";
738     }
739   else if (info->flags & G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE)
740     {
741       access_string = "write";
742     }
743   else
744     {
745       g_assert_not_reached ();
746     }
747
748   g_string_append_printf (string_builder, "%*s<property type=\"%s\" name=\"%s\" access=\"%s\"",
749                           indent, "",
750                           info->signature,
751                           info->name,
752                           access_string);
753
754   if (info->annotations == NULL)
755     {
756       g_string_append (string_builder, "/>\n");
757     }
758   else
759     {
760       g_string_append (string_builder, ">\n");
761
762       for (n = 0; info->annotations != NULL && info->annotations[n] != NULL; n++)
763         g_dbus_annotation_info_generate_xml (info->annotations[n],
764                                                indent + 2,
765                                                string_builder);
766
767       g_string_append_printf (string_builder, "%*s</property>\n", indent, "");
768     }
769
770 }
771
772 /**
773  * g_dbus_interface_info_generate_xml:
774  * @info: A #GDBusNodeInfo
775  * @indent: Indentation level.
776  * @string_builder: A #GString to to append XML data to.
777  *
778  * Appends an XML representation of @info (and its children) to @string_builder.
779  *
780  * This function is typically used for generating introspection XML
781  * documents at run-time for handling the
782  * <literal>org.freedesktop.DBus.Introspectable.Introspect</literal>
783  * method.
784  *
785  * Since: 2.26
786  */
787 void
788 g_dbus_interface_info_generate_xml (GDBusInterfaceInfo *info,
789                                     guint               indent,
790                                     GString            *string_builder)
791 {
792   guint n;
793
794   g_string_append_printf (string_builder, "%*s<interface name=\"%s\">\n",
795                           indent, "",
796                           info->name);
797
798   for (n = 0; info->annotations != NULL && info->annotations[n] != NULL; n++)
799     g_dbus_annotation_info_generate_xml (info->annotations[n],
800                                          indent + 2,
801                                          string_builder);
802
803   for (n = 0; info->methods != NULL && info->methods[n] != NULL; n++)
804     g_dbus_method_info_generate_xml (info->methods[n],
805                                      indent + 2,
806                                      string_builder);
807
808   for (n = 0; info->signals != NULL && info->signals[n] != NULL; n++)
809     g_dbus_signal_info_generate_xml (info->signals[n],
810                                      indent + 2,
811                                      string_builder);
812
813   for (n = 0; info->properties != NULL && info->properties[n] != NULL; n++)
814     g_dbus_property_info_generate_xml (info->properties[n],
815                                        indent + 2,
816                                        string_builder);
817
818   g_string_append_printf (string_builder, "%*s</interface>\n", indent, "");
819 }
820
821 /**
822  * g_dbus_node_info_generate_xml:
823  * @info: A #GDBusNodeInfo.
824  * @indent: Indentation level.
825  * @string_builder: A #GString to to append XML data to.
826  *
827  * Appends an XML representation of @info (and its children) to @string_builder.
828  *
829  * This function is typically used for generating introspection XML documents at run-time for
830  * handling the <literal>org.freedesktop.DBus.Introspectable.Introspect</literal> method.
831  *
832  * Since: 2.26
833  */
834 void
835 g_dbus_node_info_generate_xml (GDBusNodeInfo *info,
836                                guint          indent,
837                                GString       *string_builder)
838 {
839   guint n;
840
841   g_string_append_printf (string_builder, "%*s<node", indent, "");
842   if (info->path != NULL)
843     g_string_append_printf (string_builder, " name=\"%s\"", info->path);
844
845   if (info->interfaces == NULL && info->nodes == NULL && info->annotations == NULL)
846     {
847       g_string_append (string_builder, "/>\n");
848     }
849   else
850     {
851       g_string_append (string_builder, ">\n");
852
853       for (n = 0; info->annotations != NULL && info->annotations[n] != NULL; n++)
854         g_dbus_annotation_info_generate_xml (info->annotations[n],
855                                              indent + 2,
856                                              string_builder);
857
858       for (n = 0; info->interfaces != NULL && info->interfaces[n] != NULL; n++)
859         g_dbus_interface_info_generate_xml (info->interfaces[n],
860                                             indent + 2,
861                                             string_builder);
862
863       for (n = 0; info->nodes != NULL && info->nodes[n] != NULL; n++)
864         g_dbus_node_info_generate_xml (info->nodes[n],
865                                        indent + 2,
866                                        string_builder);
867
868       g_string_append_printf (string_builder, "%*s</node>\n", indent, "");
869     }
870 }
871
872 /* ---------------------------------------------------------------------------------------------------- */
873
874 static GDBusAnnotationInfo **
875 parse_data_steal_annotations (ParseData *data,
876                               guint     *out_num_elements)
877 {
878   GDBusAnnotationInfo **ret;
879   if (out_num_elements != NULL)
880     *out_num_elements = data->annotations->len;
881   if (data->annotations == NULL)
882     ret = NULL;
883   else
884     {
885       g_ptr_array_add (data->annotations, NULL);
886       ret = (GDBusAnnotationInfo **) g_ptr_array_free (data->annotations, FALSE);
887     }
888   data->annotations = g_ptr_array_new ();
889   return ret;
890 }
891
892 static GDBusArgInfo **
893 parse_data_steal_args (ParseData *data,
894                        guint     *out_num_elements)
895 {
896   GDBusArgInfo **ret;
897   if (out_num_elements != NULL)
898     *out_num_elements = data->args->len;
899   if (data->args == NULL)
900     ret = NULL;
901   else
902     {
903       g_ptr_array_add (data->args, NULL);
904       ret = (GDBusArgInfo **) g_ptr_array_free (data->args, FALSE);
905     }
906   data->args = g_ptr_array_new ();
907   return ret;
908 }
909
910 static GDBusArgInfo **
911 parse_data_steal_out_args (ParseData *data,
912                            guint     *out_num_elements)
913 {
914   GDBusArgInfo **ret;
915   if (out_num_elements != NULL)
916     *out_num_elements = data->out_args->len;
917   if (data->out_args == NULL)
918     ret = NULL;
919   else
920     {
921       g_ptr_array_add (data->out_args, NULL);
922       ret = (GDBusArgInfo **) g_ptr_array_free (data->out_args, FALSE);
923     }
924   data->out_args = g_ptr_array_new ();
925   return ret;
926 }
927
928 static GDBusMethodInfo **
929 parse_data_steal_methods (ParseData *data,
930                           guint     *out_num_elements)
931 {
932   GDBusMethodInfo **ret;
933   if (out_num_elements != NULL)
934     *out_num_elements = data->methods->len;
935   if (data->methods == NULL)
936     ret = NULL;
937   else
938     {
939       g_ptr_array_add (data->methods, NULL);
940       ret = (GDBusMethodInfo **) g_ptr_array_free (data->methods, FALSE);
941     }
942   data->methods = g_ptr_array_new ();
943   return ret;
944 }
945
946 static GDBusSignalInfo **
947 parse_data_steal_signals (ParseData *data,
948                           guint     *out_num_elements)
949 {
950   GDBusSignalInfo **ret;
951   if (out_num_elements != NULL)
952     *out_num_elements = data->signals->len;
953   if (data->signals == NULL)
954     ret = NULL;
955   else
956     {
957       g_ptr_array_add (data->signals, NULL);
958       ret = (GDBusSignalInfo **) g_ptr_array_free (data->signals, FALSE);
959     }
960   data->signals = g_ptr_array_new ();
961   return ret;
962 }
963
964 static GDBusPropertyInfo **
965 parse_data_steal_properties (ParseData *data,
966                              guint     *out_num_elements)
967 {
968   GDBusPropertyInfo **ret;
969   if (out_num_elements != NULL)
970     *out_num_elements = data->properties->len;
971   if (data->properties == NULL)
972     ret = NULL;
973   else
974     {
975       g_ptr_array_add (data->properties, NULL);
976       ret = (GDBusPropertyInfo **) g_ptr_array_free (data->properties, FALSE);
977     }
978   data->properties = g_ptr_array_new ();
979   return ret;
980 }
981
982 static GDBusInterfaceInfo **
983 parse_data_steal_interfaces (ParseData *data,
984                              guint     *out_num_elements)
985 {
986   GDBusInterfaceInfo **ret;
987   if (out_num_elements != NULL)
988     *out_num_elements = data->interfaces->len;
989   if (data->interfaces == NULL)
990     ret = NULL;
991   else
992     {
993       g_ptr_array_add (data->interfaces, NULL);
994       ret = (GDBusInterfaceInfo **) g_ptr_array_free (data->interfaces, FALSE);
995     }
996   data->interfaces = g_ptr_array_new ();
997   return ret;
998 }
999
1000 static GDBusNodeInfo **
1001 parse_data_steal_nodes (ParseData *data,
1002                         guint     *out_num_elements)
1003 {
1004   GDBusNodeInfo **ret;
1005   if (out_num_elements != NULL)
1006     *out_num_elements = data->nodes->len;
1007   if (data->nodes == NULL)
1008     ret = NULL;
1009   else
1010     {
1011       g_ptr_array_add (data->nodes, NULL);
1012       ret = (GDBusNodeInfo **) g_ptr_array_free (data->nodes, FALSE);
1013     }
1014   data->nodes = g_ptr_array_new ();
1015   return ret;
1016 }
1017
1018 /* ---------------------------------------------------------------------------------------------------- */
1019
1020 static void
1021 parse_data_free_annotations (ParseData *data)
1022 {
1023   if (data->annotations == NULL)
1024     return;
1025   g_ptr_array_foreach (data->annotations, (GFunc) g_dbus_annotation_info_unref, NULL);
1026   g_ptr_array_free (data->annotations, TRUE);
1027   data->annotations = NULL;
1028 }
1029
1030 static void
1031 parse_data_free_args (ParseData *data)
1032 {
1033   if (data->args == NULL)
1034     return;
1035   g_ptr_array_foreach (data->args, (GFunc) g_dbus_arg_info_unref, NULL);
1036   g_ptr_array_free (data->args, TRUE);
1037   data->args = NULL;
1038 }
1039
1040 static void
1041 parse_data_free_out_args (ParseData *data)
1042 {
1043   if (data->out_args == NULL)
1044     return;
1045   g_ptr_array_foreach (data->out_args, (GFunc) g_dbus_arg_info_unref, NULL);
1046   g_ptr_array_free (data->out_args, TRUE);
1047   data->out_args = NULL;
1048 }
1049
1050 static void
1051 parse_data_free_methods (ParseData *data)
1052 {
1053   if (data->methods == NULL)
1054     return;
1055   g_ptr_array_foreach (data->methods, (GFunc) g_dbus_method_info_unref, NULL);
1056   g_ptr_array_free (data->methods, TRUE);
1057   data->methods = NULL;
1058 }
1059
1060 static void
1061 parse_data_free_signals (ParseData *data)
1062 {
1063   if (data->signals == NULL)
1064     return;
1065   g_ptr_array_foreach (data->signals, (GFunc) g_dbus_signal_info_unref, NULL);
1066   g_ptr_array_free (data->signals, TRUE);
1067   data->signals = NULL;
1068 }
1069
1070 static void
1071 parse_data_free_properties (ParseData *data)
1072 {
1073   if (data->properties == NULL)
1074     return;
1075   g_ptr_array_foreach (data->properties, (GFunc) g_dbus_property_info_unref, NULL);
1076   g_ptr_array_free (data->properties, TRUE);
1077   data->properties = NULL;
1078 }
1079
1080 static void
1081 parse_data_free_interfaces (ParseData *data)
1082 {
1083   if (data->interfaces == NULL)
1084     return;
1085   g_ptr_array_foreach (data->interfaces, (GFunc) g_dbus_interface_info_unref, NULL);
1086   g_ptr_array_free (data->interfaces, TRUE);
1087   data->interfaces = NULL;
1088 }
1089
1090 static void
1091 parse_data_free_nodes (ParseData *data)
1092 {
1093   if (data->nodes == NULL)
1094     return;
1095   g_ptr_array_foreach (data->nodes, (GFunc) g_dbus_node_info_unref, NULL);
1096   g_ptr_array_free (data->nodes, TRUE);
1097   data->nodes = NULL;
1098 }
1099
1100 /* ---------------------------------------------------------------------------------------------------- */
1101
1102 static GDBusAnnotationInfo *
1103 parse_data_get_annotation (ParseData *data,
1104                            gboolean   create_new)
1105 {
1106   if (create_new)
1107     g_ptr_array_add (data->annotations, g_new0 (GDBusAnnotationInfo, 1));
1108   return data->annotations->pdata[data->annotations->len - 1];
1109 }
1110
1111 static GDBusArgInfo *
1112 parse_data_get_arg (ParseData *data,
1113                     gboolean   create_new)
1114 {
1115   if (create_new)
1116     g_ptr_array_add (data->args, g_new0 (GDBusArgInfo, 1));
1117   return data->args->pdata[data->args->len - 1];
1118 }
1119
1120 static GDBusArgInfo *
1121 parse_data_get_out_arg (ParseData *data,
1122                         gboolean   create_new)
1123 {
1124   if (create_new)
1125     g_ptr_array_add (data->out_args, g_new0 (GDBusArgInfo, 1));
1126   return data->out_args->pdata[data->out_args->len - 1];
1127 }
1128
1129 static GDBusMethodInfo *
1130 parse_data_get_method (ParseData *data,
1131                        gboolean   create_new)
1132 {
1133   if (create_new)
1134     g_ptr_array_add (data->methods, g_new0 (GDBusMethodInfo, 1));
1135   return data->methods->pdata[data->methods->len - 1];
1136 }
1137
1138 static GDBusSignalInfo *
1139 parse_data_get_signal (ParseData *data,
1140                        gboolean   create_new)
1141 {
1142   if (create_new)
1143     g_ptr_array_add (data->signals, g_new0 (GDBusSignalInfo, 1));
1144   return data->signals->pdata[data->signals->len - 1];
1145 }
1146
1147 static GDBusPropertyInfo *
1148 parse_data_get_property (ParseData *data,
1149                          gboolean   create_new)
1150 {
1151   if (create_new)
1152     g_ptr_array_add (data->properties, g_new0 (GDBusPropertyInfo, 1));
1153   return data->properties->pdata[data->properties->len - 1];
1154 }
1155
1156 static GDBusInterfaceInfo *
1157 parse_data_get_interface (ParseData *data,
1158                           gboolean   create_new)
1159 {
1160   if (create_new)
1161     g_ptr_array_add (data->interfaces, g_new0 (GDBusInterfaceInfo, 1));
1162   return data->interfaces->pdata[data->interfaces->len - 1];
1163 }
1164
1165 static GDBusNodeInfo *
1166 parse_data_get_node (ParseData *data,
1167                      gboolean   create_new)
1168 {
1169   if (create_new)
1170     g_ptr_array_add (data->nodes, g_new0 (GDBusNodeInfo, 1));
1171   return data->nodes->pdata[data->nodes->len - 1];
1172 }
1173
1174 /* ---------------------------------------------------------------------------------------------------- */
1175
1176 static ParseData *
1177 parse_data_new (void)
1178 {
1179   ParseData *data;
1180
1181   data = g_new0 (ParseData, 1);
1182
1183   /* initialize arrays */
1184   parse_data_steal_annotations (data, NULL);
1185   parse_data_steal_args (data, NULL);
1186   parse_data_steal_out_args (data, NULL);
1187   parse_data_steal_methods (data, NULL);
1188   parse_data_steal_signals (data, NULL);
1189   parse_data_steal_properties (data, NULL);
1190   parse_data_steal_interfaces (data, NULL);
1191   parse_data_steal_nodes (data, NULL);
1192
1193   return data;
1194 }
1195
1196 static void
1197 parse_data_free (ParseData *data)
1198 {
1199   GSList *l;
1200
1201   /* free stack of annotation arrays */
1202   for (l = data->annotations_stack; l != NULL; l = l->next)
1203     {
1204       GPtrArray *annotations = l->data;
1205       g_ptr_array_foreach (annotations, (GFunc) g_dbus_annotation_info_unref, NULL);
1206       g_ptr_array_free (annotations, TRUE);
1207     }
1208   g_slist_free (data->annotations_stack);
1209
1210   /* free stack of interface arrays */
1211   for (l = data->interfaces_stack; l != NULL; l = l->next)
1212     {
1213       GPtrArray *interfaces = l->data;
1214       g_ptr_array_foreach (interfaces, (GFunc) g_dbus_interface_info_unref, NULL);
1215       g_ptr_array_free (interfaces, TRUE);
1216     }
1217   g_slist_free (data->interfaces_stack);
1218
1219   /* free stack of node arrays */
1220   for (l = data->nodes_stack; l != NULL; l = l->next)
1221     {
1222       GPtrArray *nodes = l->data;
1223       g_ptr_array_foreach (nodes, (GFunc) g_dbus_node_info_unref, NULL);
1224       g_ptr_array_free (nodes, TRUE);
1225     }
1226   g_slist_free (data->nodes_stack);
1227
1228   /* free arrays (data->annotations, data->interfaces and data->nodes have been freed above) */
1229   parse_data_free_args (data);
1230   parse_data_free_out_args (data);
1231   parse_data_free_methods (data);
1232   parse_data_free_signals (data);
1233   parse_data_free_properties (data);
1234   parse_data_free_interfaces (data);
1235   parse_data_free_annotations (data);
1236   parse_data_free_nodes (data);
1237
1238   g_free (data);
1239 }
1240
1241 /* ---------------------------------------------------------------------------------------------------- */
1242
1243 static void
1244 parser_start_element (GMarkupParseContext  *context,
1245                       const gchar          *element_name,
1246                       const gchar         **attribute_names,
1247                       const gchar         **attribute_values,
1248                       gpointer              user_data,
1249                       GError              **error)
1250 {
1251   ParseData *data = user_data;
1252   GSList *stack;
1253   const gchar *name;
1254   const gchar *type;
1255   const gchar *access;
1256   const gchar *direction;
1257   const gchar *value;
1258
1259   name = NULL;
1260   type = NULL;
1261   access = NULL;
1262   direction = NULL;
1263   value = NULL;
1264
1265   stack = (GSList *) g_markup_parse_context_get_element_stack (context);
1266
1267   /* ---------------------------------------------------------------------------------------------------- */
1268   if (strcmp (element_name, "node") == 0)
1269     {
1270       if (!(g_slist_length (stack) >= 1 || strcmp (stack->next->data, "node") != 0))
1271         {
1272           g_set_error_literal (error,
1273                                G_MARKUP_ERROR,
1274                                G_MARKUP_ERROR_INVALID_CONTENT,
1275                                "<node> elements can only be top-level or embedded in other <node> elements");
1276           goto out;
1277         }
1278
1279       if (!g_markup_collect_attributes (element_name,
1280                                         attribute_names,
1281                                         attribute_values,
1282                                         error,
1283                                         G_MARKUP_COLLECT_STRING | G_MARKUP_COLLECT_OPTIONAL, "name", &name,
1284                                         /* some hand-written introspection XML documents use this */
1285                                         G_MARKUP_COLLECT_STRING | G_MARKUP_COLLECT_OPTIONAL, "xmlns:doc", NULL,
1286                                         G_MARKUP_COLLECT_INVALID))
1287         goto out;
1288
1289       g_dbus_node_info_set (data,
1290                             parse_data_get_node (data, TRUE),
1291                             name,
1292                             NULL,
1293                             NULL,
1294                             NULL);
1295
1296       /* push the currently retrieved interfaces and nodes on the stack and prepare new arrays */
1297       data->interfaces_stack = g_slist_prepend (data->interfaces_stack, data->interfaces);
1298       data->interfaces = NULL;
1299       parse_data_steal_interfaces (data, NULL);
1300
1301       data->nodes_stack = g_slist_prepend (data->nodes_stack, data->nodes);
1302       data->nodes = NULL;
1303       parse_data_steal_nodes (data, NULL);
1304
1305     }
1306   /* ---------------------------------------------------------------------------------------------------- */
1307   else if (strcmp (element_name, "interface") == 0)
1308     {
1309       if (g_slist_length (stack) < 2 || strcmp (stack->next->data, "node") != 0)
1310         {
1311           g_set_error_literal (error,
1312                                G_MARKUP_ERROR,
1313                                G_MARKUP_ERROR_INVALID_CONTENT,
1314                                "<interface> elements can only be embedded in <node> elements");
1315           goto out;
1316         }
1317
1318       if (!g_markup_collect_attributes (element_name,
1319                                         attribute_names,
1320                                         attribute_values,
1321                                         error,
1322                                         G_MARKUP_COLLECT_STRING, "name", &name,
1323                                         G_MARKUP_COLLECT_INVALID))
1324         goto out;
1325
1326       g_dbus_interface_info_set (data,
1327                                  parse_data_get_interface (data, TRUE),
1328                                  name,
1329                                  NULL,
1330                                  NULL,
1331                                  NULL,
1332                                  NULL);
1333
1334     }
1335   /* ---------------------------------------------------------------------------------------------------- */
1336   else if (strcmp (element_name, "method") == 0)
1337     {
1338       if (g_slist_length (stack) < 2 || strcmp (stack->next->data, "interface") != 0)
1339         {
1340           g_set_error_literal (error,
1341                                G_MARKUP_ERROR,
1342                                G_MARKUP_ERROR_INVALID_CONTENT,
1343                                "<method> elements can only be embedded in <interface> elements");
1344           goto out;
1345         }
1346
1347       if (!g_markup_collect_attributes (element_name,
1348                                         attribute_names,
1349                                         attribute_values,
1350                                         error,
1351                                         G_MARKUP_COLLECT_STRING, "name", &name,
1352                                         G_MARKUP_COLLECT_INVALID))
1353         goto out;
1354
1355       g_dbus_method_info_set (data,
1356                               parse_data_get_method (data, TRUE),
1357                               name,
1358                               NULL,
1359                               NULL,
1360                               NULL);
1361
1362       data->num_args = 0;
1363
1364     }
1365   /* ---------------------------------------------------------------------------------------------------- */
1366   else if (strcmp (element_name, "signal") == 0)
1367     {
1368       if (g_slist_length (stack) < 2 || strcmp (stack->next->data, "interface") != 0)
1369         {
1370           g_set_error_literal (error,
1371                                G_MARKUP_ERROR,
1372                                G_MARKUP_ERROR_INVALID_CONTENT,
1373                                "<signal> elements can only be embedded in <interface> elements");
1374           goto out;
1375         }
1376
1377       if (!g_markup_collect_attributes (element_name,
1378                                         attribute_names,
1379                                         attribute_values,
1380                                         error,
1381                                         G_MARKUP_COLLECT_STRING, "name", &name,
1382                                         G_MARKUP_COLLECT_INVALID))
1383         goto out;
1384
1385       g_dbus_signal_info_set (data,
1386                               parse_data_get_signal (data, TRUE),
1387                               name,
1388                               NULL,
1389                               NULL);
1390
1391       data->num_args = 0;
1392
1393     }
1394   /* ---------------------------------------------------------------------------------------------------- */
1395   else if (strcmp (element_name, "property") == 0)
1396     {
1397       GDBusPropertyInfoFlags flags;
1398
1399       if (g_slist_length (stack) < 2 || strcmp (stack->next->data, "interface") != 0)
1400         {
1401           g_set_error_literal (error,
1402                                G_MARKUP_ERROR,
1403                                G_MARKUP_ERROR_INVALID_CONTENT,
1404                                "<property> elements can only be embedded in <interface> elements");
1405           goto out;
1406         }
1407
1408       if (!g_markup_collect_attributes (element_name,
1409                                         attribute_names,
1410                                         attribute_values,
1411                                         error,
1412                                         G_MARKUP_COLLECT_STRING, "name", &name,
1413                                         G_MARKUP_COLLECT_STRING, "type", &type,
1414                                         G_MARKUP_COLLECT_STRING, "access", &access,
1415                                         G_MARKUP_COLLECT_INVALID))
1416         goto out;
1417
1418       if (strcmp (access, "read") == 0)
1419         flags = G_DBUS_PROPERTY_INFO_FLAGS_READABLE;
1420       else if (strcmp (access, "write") == 0)
1421         flags = G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE;
1422       else if (strcmp (access, "readwrite") == 0)
1423         flags = G_DBUS_PROPERTY_INFO_FLAGS_READABLE | G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE;
1424       else
1425         {
1426           g_set_error (error,
1427                        G_MARKUP_ERROR,
1428                        G_MARKUP_ERROR_INVALID_CONTENT,
1429                        "Unknown value '%s' of access attribute for element <property>",
1430                        access);
1431           goto out;
1432         }
1433
1434       g_dbus_property_info_set (data,
1435                                 parse_data_get_property (data, TRUE),
1436                                 name,
1437                                 type,
1438                                 flags,
1439                                 NULL);
1440
1441     }
1442   /* ---------------------------------------------------------------------------------------------------- */
1443   else if (strcmp (element_name, "arg") == 0)
1444     {
1445       gboolean is_in;
1446       gchar *name_to_use;
1447
1448       if (g_slist_length (stack) < 2 ||
1449           (strcmp (stack->next->data, "method") != 0 &&
1450            strcmp (stack->next->data, "signal") != 0))
1451         {
1452           g_set_error_literal (error,
1453                                G_MARKUP_ERROR,
1454                                G_MARKUP_ERROR_INVALID_CONTENT,
1455                                "<arg> elements can only be embedded in <method> or <signal> elements");
1456           goto out;
1457         }
1458
1459       if (!g_markup_collect_attributes (element_name,
1460                                         attribute_names,
1461                                         attribute_values,
1462                                         error,
1463                                         G_MARKUP_COLLECT_STRING | G_MARKUP_COLLECT_OPTIONAL, "name", &name,
1464                                         G_MARKUP_COLLECT_STRING | G_MARKUP_COLLECT_OPTIONAL, "direction", &direction,
1465                                         G_MARKUP_COLLECT_STRING, "type", &type,
1466                                         G_MARKUP_COLLECT_INVALID))
1467         goto out;
1468
1469       if (strcmp (stack->next->data, "method") == 0)
1470         is_in = TRUE;
1471       else
1472         is_in = FALSE;
1473       if (direction != NULL)
1474         {
1475           if (strcmp (direction, "in") == 0)
1476             is_in = TRUE;
1477           else if (strcmp (direction, "out") == 0)
1478             is_in = FALSE;
1479           else
1480             {
1481               g_set_error (error,
1482                            G_MARKUP_ERROR,
1483                            G_MARKUP_ERROR_INVALID_CONTENT,
1484                            "Unknown value '%s' of direction attribute",
1485                            direction);
1486               goto out;
1487             }
1488         }
1489
1490       if (is_in && strcmp (stack->next->data, "signal") == 0)
1491         {
1492           g_set_error_literal (error,
1493                                G_MARKUP_ERROR,
1494                                G_MARKUP_ERROR_INVALID_CONTENT,
1495                                "Only direction 'out' is allowed for <arg> elements embedded in <signal>");
1496           goto out;
1497         }
1498
1499       if (name == NULL)
1500         name_to_use = g_strdup_printf ("arg_%d", data->num_args);
1501       else
1502         name_to_use = g_strdup (name);
1503       data->num_args++;
1504
1505       if (is_in)
1506         {
1507           g_dbus_arg_info_set (data,
1508                                parse_data_get_arg (data, TRUE),
1509                                name_to_use,
1510                                type,
1511                                NULL);
1512           data->last_arg_was_in = TRUE;
1513         }
1514       else
1515         {
1516           g_dbus_arg_info_set (data,
1517                                parse_data_get_out_arg (data, TRUE),
1518                                name_to_use,
1519                                type,
1520                                NULL);
1521           data->last_arg_was_in = FALSE;
1522
1523         }
1524
1525       g_free (name_to_use);
1526     }
1527   /* ---------------------------------------------------------------------------------------------------- */
1528   else if (strcmp (element_name, "annotation") == 0)
1529     {
1530       if (g_slist_length (stack) < 2 ||
1531           (strcmp (stack->next->data, "node") != 0 &&
1532            strcmp (stack->next->data, "interface") != 0 &&
1533            strcmp (stack->next->data, "signal") != 0 &&
1534            strcmp (stack->next->data, "method") != 0 &&
1535            strcmp (stack->next->data, "property") != 0 &&
1536            strcmp (stack->next->data, "arg") != 0 &&
1537            strcmp (stack->next->data, "annotation") != 0))
1538         {
1539           g_set_error_literal (error,
1540                                G_MARKUP_ERROR,
1541                                G_MARKUP_ERROR_INVALID_CONTENT,
1542                                "<annotation> elements can only be embedded in <node>, <interface>, <signal>, <method>, <property>, <arg> or <annotation> elements");
1543           goto out;
1544         }
1545
1546       if (!g_markup_collect_attributes (element_name,
1547                                         attribute_names,
1548                                         attribute_values,
1549                                         error,
1550                                         G_MARKUP_COLLECT_STRING, "name", &name,
1551                                         G_MARKUP_COLLECT_STRING, "value", &value,
1552                                         G_MARKUP_COLLECT_INVALID))
1553         goto out;
1554
1555       g_dbus_annotation_info_set (data,
1556                                   parse_data_get_annotation (data, TRUE),
1557                                   name,
1558                                   value,
1559                                   NULL);
1560     }
1561   /* ---------------------------------------------------------------------------------------------------- */
1562   else
1563     {
1564       /* don't bail on unknown elements; just ignore them */
1565     }
1566   /* ---------------------------------------------------------------------------------------------------- */
1567
1568   /* push the currently retrieved annotations on the stack and prepare a new one */
1569   data->annotations_stack = g_slist_prepend (data->annotations_stack, data->annotations);
1570   data->annotations = NULL;
1571   parse_data_steal_annotations (data, NULL);
1572
1573  out:
1574   ;
1575 }
1576
1577 /* ---------------------------------------------------------------------------------------------------- */
1578
1579 static GDBusAnnotationInfo **
1580 steal_annotations (ParseData *data)
1581 {
1582   return parse_data_steal_annotations (data, NULL);
1583 }
1584
1585
1586 static void
1587 parser_end_element (GMarkupParseContext  *context,
1588                     const gchar          *element_name,
1589                     gpointer              user_data,
1590                     GError              **error)
1591 {
1592   ParseData *data = user_data;
1593   gboolean have_popped_annotations;
1594
1595   have_popped_annotations = FALSE;
1596
1597   if (strcmp (element_name, "node") == 0)
1598     {
1599       guint num_nodes;
1600       guint num_interfaces;
1601       GDBusNodeInfo **nodes;
1602       GDBusInterfaceInfo **interfaces;
1603
1604       nodes = parse_data_steal_nodes (data, &num_nodes);
1605       interfaces = parse_data_steal_interfaces (data, &num_interfaces);
1606
1607       /* destroy the nodes, interfaces for scope we're exiting and and pop the nodes, interfaces from the
1608        * scope we're reentering
1609        */
1610       parse_data_free_interfaces (data);
1611       data->interfaces = (GPtrArray *) data->interfaces_stack->data;
1612       data->interfaces_stack = g_slist_remove (data->interfaces_stack, data->interfaces_stack->data);
1613
1614       parse_data_free_nodes (data);
1615       data->nodes = (GPtrArray *) data->nodes_stack->data;
1616       data->nodes_stack = g_slist_remove (data->nodes_stack, data->nodes_stack->data);
1617
1618       g_dbus_node_info_set (data,
1619                             parse_data_get_node (data, FALSE),
1620                             NULL,
1621                             interfaces,
1622                             nodes,
1623                             steal_annotations (data));
1624
1625     }
1626   else if (strcmp (element_name, "interface") == 0)
1627     {
1628       guint num_methods;
1629       guint num_signals;
1630       guint num_properties;
1631       GDBusMethodInfo **methods;
1632       GDBusSignalInfo **signals;
1633       GDBusPropertyInfo **properties;
1634
1635       methods    = parse_data_steal_methods    (data, &num_methods);
1636       signals    = parse_data_steal_signals    (data, &num_signals);
1637       properties = parse_data_steal_properties (data, &num_properties);
1638
1639       g_dbus_interface_info_set (data,
1640                                  parse_data_get_interface (data, FALSE),
1641                                  NULL,
1642                                  methods,
1643                                  signals,
1644                                  properties,
1645                                  steal_annotations (data));
1646
1647     }
1648   else if (strcmp (element_name, "method") == 0)
1649     {
1650       guint in_num_args;
1651       guint out_num_args;
1652       GDBusArgInfo **in_args;
1653       GDBusArgInfo **out_args;
1654
1655       in_args  = parse_data_steal_args     (data, &in_num_args);
1656       out_args = parse_data_steal_out_args (data, &out_num_args);
1657
1658       g_dbus_method_info_set (data,
1659                               parse_data_get_method (data, FALSE),
1660                               NULL,
1661                               in_args,
1662                               out_args,
1663                               steal_annotations (data));
1664     }
1665   else if (strcmp (element_name, "signal") == 0)
1666     {
1667       guint num_args;
1668       GDBusArgInfo **args;
1669
1670       args = parse_data_steal_out_args (data, &num_args);
1671
1672       g_dbus_signal_info_set (data,
1673                               parse_data_get_signal (data, FALSE),
1674                               NULL,
1675                               args,
1676                               steal_annotations (data));
1677     }
1678   else if (strcmp (element_name, "property") == 0)
1679     {
1680       g_dbus_property_info_set (data,
1681                                 parse_data_get_property (data, FALSE),
1682                                 NULL,
1683                                 NULL,
1684                                 G_DBUS_PROPERTY_INFO_FLAGS_NONE,
1685                                 steal_annotations (data));
1686     }
1687   else if (strcmp (element_name, "arg") == 0)
1688     {
1689       g_dbus_arg_info_set (data,
1690                            data->last_arg_was_in ? parse_data_get_arg (data, FALSE) : parse_data_get_out_arg (data, FALSE),
1691                            NULL,
1692                            NULL,
1693                            steal_annotations (data));
1694     }
1695   else if (strcmp (element_name, "annotation") == 0)
1696     {
1697       GDBusAnnotationInfo **embedded_annotations;
1698
1699       embedded_annotations = steal_annotations (data);
1700
1701       /* destroy the annotations for scope we're exiting and and pop the annotations from the scope we're reentering */
1702       parse_data_free_annotations (data);
1703       data->annotations = (GPtrArray *) data->annotations_stack->data;
1704       data->annotations_stack = g_slist_remove (data->annotations_stack, data->annotations_stack->data);
1705
1706       have_popped_annotations = TRUE;
1707
1708       g_dbus_annotation_info_set (data,
1709                                   parse_data_get_annotation (data, FALSE),
1710                                   NULL,
1711                                   NULL,
1712                                   embedded_annotations);
1713     }
1714   else
1715     {
1716       /* don't bail on unknown elements; just ignore them */
1717     }
1718
1719   if (!have_popped_annotations)
1720     {
1721       /* destroy the annotations for scope we're exiting and and pop the annotations from the scope we're reentering */
1722       parse_data_free_annotations (data);
1723       data->annotations = (GPtrArray *) data->annotations_stack->data;
1724       data->annotations_stack = g_slist_remove (data->annotations_stack, data->annotations_stack->data);
1725     }
1726 }
1727
1728 /* ---------------------------------------------------------------------------------------------------- */
1729
1730 static void
1731 parser_error (GMarkupParseContext *context,
1732               GError              *error,
1733               gpointer             user_data)
1734 {
1735   gint line_number;
1736   gint char_number;
1737
1738   g_markup_parse_context_get_position (context, &line_number, &char_number);
1739
1740   g_prefix_error (&error, "%d:%d: ",
1741                   line_number,
1742                   char_number);
1743 }
1744
1745 /* ---------------------------------------------------------------------------------------------------- */
1746
1747 /**
1748  * g_dbus_node_info_new_for_xml:
1749  * @xml_data: Valid D-Bus introspection XML.
1750  * @error: Return location for error.
1751  *
1752  * Parses @xml_data and returns a #GDBusNodeInfo representing the data.
1753  *
1754  * Returns: A #GDBusNodeInfo structure or %NULL if @error is set. Free
1755  * with g_dbus_node_info_unref().
1756  *
1757  * Since: 2.26
1758  */
1759 GDBusNodeInfo *
1760 g_dbus_node_info_new_for_xml (const gchar  *xml_data,
1761                               GError      **error)
1762 {
1763   GDBusNodeInfo *ret;
1764   GMarkupParseContext *context;
1765   GMarkupParser *parser;
1766   guint num_nodes;
1767   ParseData *data;
1768   GDBusNodeInfo **ughret;
1769
1770   ret = NULL;
1771   parser = NULL;
1772   context = NULL;
1773
1774   parser = g_new0 (GMarkupParser, 1);
1775   parser->start_element = parser_start_element;
1776   parser->end_element   = parser_end_element;
1777   parser->error         = parser_error;
1778
1779   data = parse_data_new ();
1780   context = g_markup_parse_context_new (parser,
1781                                         0,
1782                                         data,
1783                                         (GDestroyNotify) parse_data_free);
1784
1785   if (!g_markup_parse_context_parse (context,
1786                                      xml_data,
1787                                      strlen (xml_data),
1788                                      error))
1789     goto out;
1790
1791   if (!g_markup_parse_context_end_parse (context, error))
1792     goto out;
1793
1794   ughret = parse_data_steal_nodes (data, &num_nodes);
1795
1796   if (num_nodes != 1)
1797     {
1798       guint n;
1799
1800       g_set_error (error,
1801                    G_MARKUP_ERROR,
1802                    G_MARKUP_ERROR_INVALID_CONTENT,
1803                    "Expected a single node in introspection XML, found %d",
1804                    num_nodes);
1805
1806       /* clean up */
1807       for (n = 0; n < num_nodes; n++)
1808         {
1809           for (n = 0; n < num_nodes; n++)
1810             {
1811               g_dbus_node_info_unref (ughret[n]);
1812               ughret[n] = NULL;
1813             }
1814         }
1815     }
1816
1817   ret = ughret[0];
1818   g_free (ughret);
1819
1820  out:
1821   if (parser != NULL)
1822     g_free (parser);
1823   if (context != NULL)
1824     g_markup_parse_context_free (context);
1825
1826   return ret;
1827 }
1828
1829 /* ---------------------------------------------------------------------------------------------------- */
1830
1831 /**
1832  * g_dbus_annotation_info_lookup:
1833  * @annotations: A %NULL-terminated array of annotations or %NULL.
1834  * @name: The name of the annotation to look up.
1835  *
1836  * Looks up the value of an annotation.
1837  *
1838  * This cost of this function is O(n) in number of annotations.
1839  *
1840  * Returns: The value or %NULL if not found. Do not free, it is owned by @annotations.
1841  *
1842  * Since: 2.26
1843  */
1844 const gchar *
1845 g_dbus_annotation_info_lookup (GDBusAnnotationInfo **annotations,
1846                                const gchar          *name)
1847 {
1848   guint n;
1849   const gchar *ret;
1850
1851   ret = NULL;
1852   for (n = 0; annotations != NULL && annotations[n] != NULL; n++)
1853     {
1854       if (g_strcmp0 (annotations[n]->key, name) == 0)
1855         {
1856           ret = annotations[n]->value;
1857           goto out;
1858         }
1859     }
1860
1861  out:
1862   return ret;
1863 }
1864
1865 /* ---------------------------------------------------------------------------------------------------- */
1866
1867 /**
1868  * g_dbus_interface_info_lookup_method:
1869  * @info: A #GDBusInterfaceInfo.
1870  * @name: A D-Bus method name (typically in CamelCase)
1871  *
1872  * Looks up information about a method.
1873  *
1874  * This cost of this function is O(n) in number of methods.
1875  *
1876  * Returns: A #GDBusMethodInfo or %NULL if not found. Do not free, it is owned by @info.
1877  *
1878  * Since: 2.26
1879  */
1880 GDBusMethodInfo *
1881 g_dbus_interface_info_lookup_method (GDBusInterfaceInfo *info,
1882                                      const gchar        *name)
1883 {
1884   guint n;
1885   GDBusMethodInfo *result;
1886
1887   for (n = 0; info->methods != NULL && info->methods[n] != NULL; n++)
1888     {
1889       GDBusMethodInfo *i = info->methods[n];
1890
1891       if (g_strcmp0 (i->name, name) == 0)
1892         {
1893           result = i;
1894           goto out;
1895         }
1896     }
1897
1898   result = NULL;
1899
1900  out:
1901   return result;
1902 }
1903
1904 /* ---------------------------------------------------------------------------------------------------- */
1905
1906 /**
1907  * g_dbus_interface_info_lookup_signal:
1908  * @info: A #GDBusInterfaceInfo.
1909  * @name: A D-Bus signal name (typically in CamelCase)
1910  *
1911  * Looks up information about a signal.
1912  *
1913  * This cost of this function is O(n) in number of signals.
1914  *
1915  * Returns: A #GDBusSignalInfo or %NULL if not found. Do not free, it is owned by @info.
1916  *
1917  * Since: 2.26
1918  */
1919 GDBusSignalInfo *
1920 g_dbus_interface_info_lookup_signal (GDBusInterfaceInfo *info,
1921                                      const gchar        *name)
1922 {
1923   guint n;
1924   GDBusSignalInfo *result;
1925
1926   for (n = 0; info->signals != NULL && info->signals[n] != NULL; n++)
1927     {
1928       GDBusSignalInfo *i = info->signals[n];
1929
1930       if (g_strcmp0 (i->name, name) == 0)
1931         {
1932           result = i;
1933           goto out;
1934         }
1935     }
1936
1937   result = NULL;
1938
1939  out:
1940   return result;
1941 }
1942
1943 /* ---------------------------------------------------------------------------------------------------- */
1944
1945 /**
1946  * g_dbus_interface_info_lookup_property:
1947  * @info: A #GDBusInterfaceInfo.
1948  * @name: A D-Bus property name (typically in CamelCase).
1949  *
1950  * Looks up information about a property.
1951  *
1952  * This cost of this function is O(n) in number of properties.
1953  *
1954  * Returns: A #GDBusPropertyInfo or %NULL if not found. Do not free, it is owned by @info.
1955  *
1956  * Since: 2.26
1957  */
1958 GDBusPropertyInfo *
1959 g_dbus_interface_info_lookup_property (GDBusInterfaceInfo *info,
1960                                        const gchar        *name)
1961 {
1962   guint n;
1963   GDBusPropertyInfo *result;
1964
1965   for (n = 0; info->properties != NULL && info->properties[n] != NULL; n++)
1966     {
1967       GDBusPropertyInfo *i = info->properties[n];
1968
1969       if (g_strcmp0 (i->name, name) == 0)
1970         {
1971           result = i;
1972           goto out;
1973         }
1974     }
1975
1976   result = NULL;
1977
1978  out:
1979   return result;
1980 }
1981
1982 /* ---------------------------------------------------------------------------------------------------- */
1983
1984 /**
1985  * g_dbus_node_info_lookup_interface:
1986  * @info: A #GDBusNodeInfo.
1987  * @name: A D-Bus interface name.
1988  *
1989  * Looks up information about an interface.
1990  *
1991  * This cost of this function is O(n) in number of interfaces.
1992  *
1993  * Returns: A #GDBusInterfaceInfo or %NULL if not found. Do not free, it is owned by @info.
1994  *
1995  * Since: 2.26
1996  */
1997 GDBusInterfaceInfo *
1998 g_dbus_node_info_lookup_interface (GDBusNodeInfo *info,
1999                                    const gchar   *name)
2000 {
2001   guint n;
2002   GDBusInterfaceInfo *result;
2003
2004   for (n = 0; info->interfaces != NULL && info->interfaces[n] != NULL; n++)
2005     {
2006       GDBusInterfaceInfo *i = info->interfaces[n];
2007
2008       if (g_strcmp0 (i->name, name) == 0)
2009         {
2010           result = i;
2011           goto out;
2012         }
2013     }
2014
2015   result = NULL;
2016
2017  out:
2018   return result;
2019 }